Skip to content

Commit

Permalink
I can't spell persistent
Browse files Browse the repository at this point in the history
  • Loading branch information
dmiller committed Jul 2, 2024
1 parent 94aeab2 commit d2f5a52
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 16 deletions.
2 changes: 1 addition & 1 deletion _posts/2023-01-16-circular-reasoning-part-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ type MyClass(x:int) =
member this.seq() = upcast this
```

The problem is that aliases are not sticky. Any program from the outside would not see that `MyClass` implements `IPersisentCollection`. It would see `IPersistentCollectionT<ISeq>`. I'm not sure I'm willing to violate expectations to that extent.
The problem is that aliases are not sticky. Any program from the outside would not see that `MyClass` implements `IPersistentCollection`. It would see `IPersistentCollectionT<ISeq>`. I'm not sure I'm willing to violate expectations to that extent.

An alternative would be to create real types:

Expand Down
10 changes: 8 additions & 2 deletions _posts/2024-07-02-persistent-hash-map-part-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ categories: general
The first of several posts on implementing immutable, persistent Hash Array Mapped Tries. This post describes the data structure at a high level; subsequent posts will provide F# code for the base implementation and then discuss transiency.


- Part 1: Making a hash of things (this post)
- [Part 2: The root]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-2 %})
- [Part 3: The guts]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-3 %})
- [Part 4: Other matters]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-4 %})
- [Part 5: At a loss]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-5 %})


# Making a hash of things

Expand All @@ -24,7 +30,7 @@ most of the rest involve iterating over the key/value pairs in the map and perfo

Because we are living in the land of the persistent and immutable, the general case for the `assoc` and `without` operations is to generate a new map with the desired change. The original map is left unchanged. (The `find` operation is a read-only operation and does not change the map.) For efficiency, we will need the new map to share as much structure are possible with the original map.

HAMTs can viewed a mash-up of simple hash tables, binary search trees and the ideas we covered when discussing _persistent bit-partitioned vector tries_ (see [Persistent vectors, Part 2 -- Immutability and persistence]({{site.baseurl}}{% post_url 2023-02-12-PersisentVector-part-2 %})).
HAMTs can viewed a mash-up of simple hash tables, binary search trees and the ideas we covered when discussing _persistent bit-partitioned vector tries_ (see [Persistent vectors, Part 2 -- Immutability and persistence]({{site.baseurl}}{% post_url 2023-02-12-PersistentVector-part-2 %})).

Let's look at some candidates structures.

Expand Down Expand Up @@ -151,4 +157,4 @@ If we want to modify the data of node 6 to be Q, we must make copies of all node

The original tree still exists, unmodified. Copying and resuse are the secrets to immutability, persistence, and efficiency.

And now we can code. In the [next post]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-2 %}), I'll cover the basics of an implementation of `PersistentHashMap` in F#.
And now we can code. In the [next post]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-2 %}), I'll cover the basics of an implementation of `PersistentHashMap` in F#.
4 changes: 2 additions & 2 deletions _posts/2024-07-02-persistent-hash-map-part-2.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ I'll sketch the code for the root of the `PersistentHashMap` structure in this p

## Refresher

You can refer to the [first post]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-1 %}) in this series for the background on HAMTs.
You can refer to the [first post]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-1 %}) in this series for the background on HAMTs.

## Interfaces

Expand Down Expand Up @@ -270,4 +270,4 @@ Finally, the `without` operation:

There is the usual special case handling for the `null` key. When we do the operation on the root, getting back the same root indicates the key was not present, so removing it was a no-op. Otherwise, we have a new root and reduced count.

In the [next post]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-3 %}), we look at the structure of the `INode` interface and the three node types that implement it.
In the [next post]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-3 %}), we look at the structure of the `INode` interface and the three node types that implement it.
6 changes: 3 additions & 3 deletions _posts/2024-07-02-persistent-hash-map-part-3.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ We take a look at the internal nodes that implement the core algorithms of the `

## Background

Take a look at [The root]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-2 %}) for the context in which these node types occur.
Take a look at [The root]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-2 %}) for the context in which these node types occur.

## The `INode` interface

Expand All @@ -37,12 +37,12 @@ type INode =

We will cover `assoc`, `without`, and the second `find`. (The first `find` is almost identical.) These are the primary operations defining map behavior.

The overloads of `assoc` and `without` that take an `AtomicBoolean` first argument are used for the `transient` version of the map, which we will cover [later]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-4 %}).
The overloads of `assoc` and `without` that take an `AtomicBoolean` first argument are used for the `transient` version of the map, which we will cover [later]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-4 %}).


## The `BitmapIndexedNode` node

The `BitmapIndexedNode` node is what we described in [the first]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-1 %}) of this series of posts. It contains a compressed array of entries -- there are no empty slots. A bitmap indicates which slots are occupied. We us the `bitCount` technique to find the actual index for an entry that is present. An entry can be a key-value pair or another node. The array itself is double-sized. It contains alternating key/value pairs. If your key maps to `i`, look at `array[2*i]`. If that is null, then `array[2*i+1]` will contain a node -- you're going to need to go down to the next level. If `array[2*i]` is not `null`, then it is an actual key. and `array[2*i]` & `array[2*i+1]` are a key-value pair. (This is why we manage `null` key presence in the root object. `null` in a key position indicates no key present.)
The `BitmapIndexedNode` node is what we described in [the first]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-1 %}) of this series of posts. It contains a compressed array of entries -- there are no empty slots. A bitmap indicates which slots are occupied. We us the `bitCount` technique to find the actual index for an entry that is present. An entry can be a key-value pair or another node. The array itself is double-sized. It contains alternating key/value pairs. If your key maps to `i`, look at `array[2*i]`. If that is null, then `array[2*i+1]` will contain a node -- you're going to need to go down to the next level. If `array[2*i]` is not `null`, then it is an actual key. and `array[2*i]` & `array[2*i+1]` are a key-value pair. (This is why we manage `null` key presence in the root object. `null` in a key position indicates no key present.)

Looking at one of the `find` methods may help:

Expand Down
8 changes: 4 additions & 4 deletions _posts/2024-07-02-persistent-hash-map-part-4.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ We continue our discussion of `PersistentHashMap` with a discussion of transienc

The previous posts in this series are:

- [Part 1: Making a hash of things (this post)]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-1 %})
- [Part 2: The root]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-2 %})
- [Part 3: The guts]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-3 %})
- [Part 1: Making a hash of things (this post)]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-1 %})
- [Part 2: The root]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-2 %})
- [Part 3: The guts]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-3 %})

# Transiency

Expand Down Expand Up @@ -79,4 +79,4 @@ Given that each variation was causing me to rework hundreds of lines of code, I

# Onward

We conclude this series of posts with a [look at performance]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-5 %}) and a comparison of the F# and Clojure versions of `PersistentHashMap`.
We conclude this series of posts with a [look at performance]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-5 %}) and a comparison of the F# and Clojure versions of `PersistentHashMap`.
8 changes: 4 additions & 4 deletions _posts/2024-07-02-persistent-hash-map-part-5.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ We look at performance of the new F# version of `PersistentHashMap` and comp

This is the final post in a series on `PersistentHashMap`. The previous posts are:

- [Part 1: Making a hash of things (this post)]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-1 %})
- [Part 2: The root]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-2 %})
- [Part 3: The guts]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-3 %})
- [Part 4: Other matters]({{site.baseurl}}{% post_url 2024-07-02-persisent-hash-map-part-4 %})
- [Part 1: Making a hash of things (this post)]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-1 %})
- [Part 2: The root]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-2 %})
- [Part 3: The guts]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-3 %})
- [Part 4: Other matters]({{site.baseurl}}{% post_url 2024-07-02-persistent-hash-map-part-4 %})

# Performance

Expand Down

0 comments on commit d2f5a52

Please sign in to comment.