diff options
-rw-r--r-- | README.md | 62 | ||||
-rw-r--r-- | deps.mk | 180 | ||||
-rw-r--r-- | src/pds.go | 403 | ||||
l--------- | tests/benchmarks/vector-append/main.go (renamed from tests/benchmarks/list-append/main.go) | 0 | ||||
-rw-r--r-- | tests/benchmarks/vector-append/pds.go (renamed from tests/benchmarks/list-append/pds.go) | 2 | ||||
l--------- | tests/benchmarks/vector-builder-append/main.go (renamed from tests/benchmarks/list-builder-append/main.go) | 0 | ||||
-rw-r--r-- | tests/benchmarks/vector-builder-append/pds.go (renamed from tests/benchmarks/list-builder-append/pds.go) | 2 | ||||
l--------- | tests/benchmarks/vector-builder-prepend/main.go (renamed from tests/benchmarks/list-builder-prepend/main.go) | 0 | ||||
-rw-r--r-- | tests/benchmarks/vector-builder-prepend/pds.go (renamed from tests/benchmarks/list-builder-prepend/pds.go) | 2 | ||||
l--------- | tests/benchmarks/vector-builder-set/main.go (renamed from tests/benchmarks/list-builder-set/main.go) | 0 | ||||
-rw-r--r-- | tests/benchmarks/vector-builder-set/pds.go (renamed from tests/benchmarks/list-builder-set/pds.go) | 2 | ||||
l--------- | tests/benchmarks/vector-iterator-backward/main.go (renamed from tests/benchmarks/list-iterator-backward/main.go) | 0 | ||||
-rw-r--r-- | tests/benchmarks/vector-iterator-backward/pds.go (renamed from tests/benchmarks/list-iterator-backward/pds.go) | 2 | ||||
l--------- | tests/benchmarks/vector-iterator-forward/main.go (renamed from tests/benchmarks/list-iterator-forward/main.go) | 0 | ||||
-rw-r--r-- | tests/benchmarks/vector-iterator-forward/pds.go (renamed from tests/benchmarks/list-iterator-forward/pds.go) | 2 | ||||
l--------- | tests/benchmarks/vector-prepend/main.go (renamed from tests/benchmarks/list-prepend/main.go) | 0 | ||||
-rw-r--r-- | tests/benchmarks/vector-prepend/pds.go (renamed from tests/benchmarks/list-prepend/pds.go) | 2 | ||||
l--------- | tests/benchmarks/vector-set/main.go (renamed from tests/benchmarks/list-set/main.go) | 0 | ||||
-rw-r--r-- | tests/benchmarks/vector-set/pds.go (renamed from tests/benchmarks/list-set/pds.go) | 2 | ||||
l--------- | tests/functional/vector-api/main.go (renamed from tests/functional/list-api/main.go) | 0 | ||||
-rw-r--r-- | tests/functional/vector-api/pds.go (renamed from tests/functional/list-api/pds.go) | 8 | ||||
l--------- | tests/functional/vector-builder-api/main.go (renamed from tests/functional/list-builder-api/main.go) | 0 | ||||
-rw-r--r-- | tests/functional/vector-builder-api/pds.go (renamed from tests/functional/list-builder-api/pds.go) | 16 | ||||
-rw-r--r-- | tests/pds.go | 172 |
24 files changed, 437 insertions, 420 deletions
@@ -2,7 +2,7 @@ Immutable [ -team as the `List` & `Map` implementations are loose ports from that project. +team as the `Vector` & `Map` implementations are loose ports from that project. -## List +## Vector -The `List` type represents a sorted, indexed collection of values and operates +The `Vector` type represents a sorted, indexed collection of values and operates similarly to a Go slice. It supports efficient append, prepend, update, and slice operations. -### Adding list elements +### Adding vector elements -Elements can be added to the end of the list with the `Append()` method or added -to the beginning of the list with the `Prepend()` method. Unlike Go slices, +Elements can be added to the end of the vector with the `Append()` method or added +to the beginning of the vector with the `Prepend()` method. Unlike Go slices, prepending is as efficient as appending. ```go -// Create a list with 3 elements. -l := immutable.NewList[string]() +// Create a vector with 3 elements. +l := immutable.NewVector[string]() l = l.Append("foo") l = l.Append("bar") l = l.Prepend("baz") @@ -45,30 +45,30 @@ fmt.Println(l.Get(1)) // "foo" fmt.Println(l.Get(2)) // "bar" ``` -Note that each change to the list results in a new list being created. These -lists are all snapshots at that point in time and cannot be changed so they +Note that each change to the vector results in a new vector being created. These +vectors are all snapshots at that point in time and cannot be changed so they are safe to share between multiple goroutines. -### Updating list elements +### Updating vector elements You can also overwrite existing elements by using the `Set()` method. In the -following example, we'll update the third element in our list and return the -new list to a new variable. You can see that our old `l` variable retains a +following example, we'll update the third element in our vector and return the +new vector to a new variable. You can see that our old `l` variable retains a snapshot of the original value. ```go -l := immutable.NewList[string]() +l := immutable.NewVector[string]() l = l.Append("foo") l = l.Append("bar") -newList := l.Set(2, "baz") +newVector := l.Set(2, "baz") fmt.Println(l.Get(1)) // "bar" -fmt.Println(newList.Get(1)) // "baz" +fmt.Println(newVector.Get(1)) // "baz" ``` -### Deriving sublists +### Deriving subvectors -You can create a sublist by using the `Slice()` method. This method works with +You can create a subvector by using the `Slice()` method. This method works with the same rules as subslicing a Go slice: ```go @@ -79,18 +79,18 @@ fmt.Println(l.Get(0)) // "baz" fmt.Println(l.Get(1)) // "foo" ``` -Please note that since `List` follows the same rules as slices, it will panic if +Please note that since `Vector` follows the same rules as slices, it will panic if you try to `Get()`, `Set()`, or `Slice()` with indexes that are outside of -the range of the `List`. +the range of the `Vector`. -### Iterating lists +### Iterating vectors -Iterators provide a clean, simple way to iterate over the elements of the list +Iterators provide a clean, simple way to iterate over the elements of the vector in order. This is more efficient than simply calling `Get()` for each index. -Below is an example of iterating over all elements of our list from above: +Below is an example of iterating over all elements of our vector from above: ```go itr := l.Iterator() @@ -107,25 +107,25 @@ By default iterators start from index zero, however, the `Seek()` method can be used to jump to a given index. -### Efficiently building lists +### Efficiently building vectors -If you are building large lists, it is significantly more efficient to use the -`ListBuilder`. It uses nearly the same API as `List` except that it updates -a list in-place until you are ready to use it. This can improve bulk list +If you are building large vectors, it is significantly more efficient to use the +`VectorBuilder`. It uses nearly the same API as `Vector` except that it updates +a vector in-place until you are ready to use it. This can improve bulk vector building by 10x or more. ```go -b := immutable.NewListBuilder[string]() +b := immutable.NewVectorBuilder[string]() b.Append("foo") b.Append("bar") b.Set(2, "baz") -l := b.List() +l := b.Vector() fmt.Println(l.Get(0)) // "foo" fmt.Println(l.Get(1)) // "baz" ``` -Builders are invalid after the call to `List()`. +Builders are invalid after the call to `Vector()`. ## Map @@ -4,14 +4,14 @@ libs.go = \ tests/benchmarks/builtin-map-set/pds.go \ tests/benchmarks/builtin-slice-append-int/pds.go \ tests/benchmarks/builtin-slice-append-interface/pds.go \ - tests/benchmarks/list-append/pds.go \ - tests/benchmarks/list-builder-append/pds.go \ - tests/benchmarks/list-builder-prepend/pds.go \ - tests/benchmarks/list-builder-set/pds.go \ - tests/benchmarks/list-iterator-backward/pds.go \ - tests/benchmarks/list-iterator-forward/pds.go \ - tests/benchmarks/list-prepend/pds.go \ - tests/benchmarks/list-set/pds.go \ + tests/benchmarks/vector-append/pds.go \ + tests/benchmarks/vector-builder-append/pds.go \ + tests/benchmarks/vector-builder-prepend/pds.go \ + tests/benchmarks/vector-builder-set/pds.go \ + tests/benchmarks/vector-iterator-backward/pds.go \ + tests/benchmarks/vector-iterator-forward/pds.go \ + tests/benchmarks/vector-prepend/pds.go \ + tests/benchmarks/vector-set/pds.go \ tests/benchmarks/map-builder-delete/pds.go \ tests/benchmarks/map-builder-set/pds.go \ tests/benchmarks/map-delete/pds.go \ @@ -23,8 +23,8 @@ libs.go = \ tests/benchmarks/sortedmap-iterator-backward/pds.go \ tests/benchmarks/sortedmap-iterator-forward/pds.go \ tests/benchmarks/sortedmap-set/pds.go \ - tests/functional/list-api/pds.go \ - tests/functional/list-builder-api/pds.go \ + tests/functional/vector-api/pds.go \ + tests/functional/vector-builder-api/pds.go \ tests/functional/map-api/pds.go \ tests/functional/map-builder-api/pds.go \ tests/functional/sortedmap-api/pds.go \ @@ -36,14 +36,14 @@ mains.go = \ tests/benchmarks/builtin-map-set/main.go \ tests/benchmarks/builtin-slice-append-int/main.go \ tests/benchmarks/builtin-slice-append-interface/main.go \ - tests/benchmarks/list-append/main.go \ - tests/benchmarks/list-builder-append/main.go \ - tests/benchmarks/list-builder-prepend/main.go \ - tests/benchmarks/list-builder-set/main.go \ - tests/benchmarks/list-iterator-backward/main.go \ - tests/benchmarks/list-iterator-forward/main.go \ - tests/benchmarks/list-prepend/main.go \ - tests/benchmarks/list-set/main.go \ + tests/benchmarks/vector-append/main.go \ + tests/benchmarks/vector-builder-append/main.go \ + tests/benchmarks/vector-builder-prepend/main.go \ + tests/benchmarks/vector-builder-set/main.go \ + tests/benchmarks/vector-iterator-backward/main.go \ + tests/benchmarks/vector-iterator-forward/main.go \ + tests/benchmarks/vector-prepend/main.go \ + tests/benchmarks/vector-set/main.go \ tests/benchmarks/map-builder-delete/main.go \ tests/benchmarks/map-builder-set/main.go \ tests/benchmarks/map-delete/main.go \ @@ -55,8 +55,8 @@ mains.go = \ tests/benchmarks/sortedmap-iterator-backward/main.go \ tests/benchmarks/sortedmap-iterator-forward/main.go \ tests/benchmarks/sortedmap-set/main.go \ - tests/functional/list-api/main.go \ - tests/functional/list-builder-api/main.go \ + tests/functional/vector-api/main.go \ + tests/functional/vector-builder-api/main.go \ tests/functional/map-api/main.go \ tests/functional/map-builder-api/main.go \ tests/functional/sortedmap-api/main.go \ @@ -64,16 +64,16 @@ mains.go = \ tests/main.go \ functional-tests/lib.go = \ - tests/functional/list-api/pds.go \ - tests/functional/list-builder-api/pds.go \ + tests/functional/vector-api/pds.go \ + tests/functional/vector-builder-api/pds.go \ tests/functional/map-api/pds.go \ tests/functional/map-builder-api/pds.go \ tests/functional/sortedmap-api/pds.go \ tests/functional/sortedmap-builder-api/pds.go \ functional-tests/main.go = \ - tests/functional/list-api/main.go \ - tests/functional/list-builder-api/main.go \ + tests/functional/vector-api/main.go \ + tests/functional/vector-builder-api/main.go \ tests/functional/map-api/main.go \ tests/functional/map-builder-api/main.go \ tests/functional/sortedmap-api/main.go \ @@ -88,14 +88,14 @@ benchmarks/lib.go = \ tests/benchmarks/builtin-map-set/pds.go \ tests/benchmarks/builtin-slice-append-int/pds.go \ tests/benchmarks/builtin-slice-append-interface/pds.go \ - tests/benchmarks/list-append/pds.go \ - tests/benchmarks/list-builder-append/pds.go \ - tests/benchmarks/list-builder-prepend/pds.go \ - tests/benchmarks/list-builder-set/pds.go \ - tests/benchmarks/list-iterator-backward/pds.go \ - tests/benchmarks/list-iterator-forward/pds.go \ - tests/benchmarks/list-prepend/pds.go \ - tests/benchmarks/list-set/pds.go \ + tests/benchmarks/vector-append/pds.go \ + tests/benchmarks/vector-builder-append/pds.go \ + tests/benchmarks/vector-builder-prepend/pds.go \ + tests/benchmarks/vector-builder-set/pds.go \ + tests/benchmarks/vector-iterator-backward/pds.go \ + tests/benchmarks/vector-iterator-forward/pds.go \ + tests/benchmarks/vector-prepend/pds.go \ + tests/benchmarks/vector-set/pds.go \ tests/benchmarks/map-builder-delete/pds.go \ tests/benchmarks/map-builder-set/pds.go \ tests/benchmarks/map-delete/pds.go \ @@ -113,14 +113,14 @@ benchmarks/main.go = \ tests/benchmarks/builtin-map-set/main.go \ tests/benchmarks/builtin-slice-append-int/main.go \ tests/benchmarks/builtin-slice-append-interface/main.go \ - tests/benchmarks/list-append/main.go \ - tests/benchmarks/list-builder-append/main.go \ - tests/benchmarks/list-builder-prepend/main.go \ - tests/benchmarks/list-builder-set/main.go \ - tests/benchmarks/list-iterator-backward/main.go \ - tests/benchmarks/list-iterator-forward/main.go \ - tests/benchmarks/list-prepend/main.go \ - tests/benchmarks/list-set/main.go \ + tests/benchmarks/vector-append/main.go \ + tests/benchmarks/vector-builder-append/main.go \ + tests/benchmarks/vector-builder-prepend/main.go \ + tests/benchmarks/vector-builder-set/main.go \ + tests/benchmarks/vector-iterator-backward/main.go \ + tests/benchmarks/vector-iterator-forward/main.go \ + tests/benchmarks/vector-prepend/main.go \ + tests/benchmarks/vector-set/main.go \ tests/benchmarks/map-builder-delete/main.go \ tests/benchmarks/map-builder-set/main.go \ tests/benchmarks/map-delete/main.go \ @@ -142,22 +142,22 @@ tests/benchmarks/builtin-slice-append-int/main.a: tests/benchmarks/builtin-slice tests/benchmarks/builtin-slice-append-int/pds.a: tests/benchmarks/builtin-slice-append-int/pds.go tests/benchmarks/builtin-slice-append-interface/main.a: tests/benchmarks/builtin-slice-append-interface/main.go tests/benchmarks/builtin-slice-append-interface/pds.a: tests/benchmarks/builtin-slice-append-interface/pds.go -tests/benchmarks/list-append/main.a: tests/benchmarks/list-append/main.go -tests/benchmarks/list-append/pds.a: tests/benchmarks/list-append/pds.go -tests/benchmarks/list-builder-append/main.a: tests/benchmarks/list-builder-append/main.go -tests/benchmarks/list-builder-append/pds.a: tests/benchmarks/list-builder-append/pds.go -tests/benchmarks/list-builder-prepend/main.a: tests/benchmarks/list-builder-prepend/main.go -tests/benchmarks/list-builder-prepend/pds.a: tests/benchmarks/list-builder-prepend/pds.go -tests/benchmarks/list-builder-set/main.a: tests/benchmarks/list-builder-set/main.go -tests/benchmarks/list-builder-set/pds.a: tests/benchmarks/list-builder-set/pds.go -tests/benchmarks/list-iterator-backward/main.a: tests/benchmarks/list-iterator-backward/main.go -tests/benchmarks/list-iterator-backward/pds.a: tests/benchmarks/list-iterator-backward/pds.go -tests/benchmarks/list-iterator-forward/main.a: tests/benchmarks/list-iterator-forward/main.go -tests/benchmarks/list-iterator-forward/pds.a: tests/benchmarks/list-iterator-forward/pds.go -tests/benchmarks/list-prepend/main.a: tests/benchmarks/list-prepend/main.go -tests/benchmarks/list-prepend/pds.a: tests/benchmarks/list-prepend/pds.go -tests/benchmarks/list-set/main.a: tests/benchmarks/list-set/main.go -tests/benchmarks/list-set/pds.a: tests/benchmarks/list-set/pds.go +tests/benchmarks/vector-append/main.a: tests/benchmarks/vector-append/main.go +tests/benchmarks/vector-append/pds.a: tests/benchmarks/vector-append/pds.go +tests/benchmarks/vector-builder-append/main.a: tests/benchmarks/vector-builder-append/main.go +tests/benchmarks/vector-builder-append/pds.a: tests/benchmarks/vector-builder-append/pds.go +tests/benchmarks/vector-builder-prepend/main.a: tests/benchmarks/vector-builder-prepend/main.go +tests/benchmarks/vector-builder-prepend/pds.a: tests/benchmarks/vector-builder-prepend/pds.go +tests/benchmarks/vector-builder-set/main.a: tests/benchmarks/vector-builder-set/main.go +tests/benchmarks/vector-builder-set/pds.a: tests/benchmarks/vector-builder-set/pds.go +tests/benchmarks/vector-iterator-backward/main.a: tests/benchmarks/vector-iterator-backward/main.go +tests/benchmarks/vector-iterator-backward/pds.a: tests/benchmarks/vector-iterator-backward/pds.go +tests/benchmarks/vector-iterator-forward/main.a: tests/benchmarks/vector-iterator-forward/main.go +tests/benchmarks/vector-iterator-forward/pds.a: tests/benchmarks/vector-iterator-forward/pds.go +tests/benchmarks/vector-prepend/main.a: tests/benchmarks/vector-prepend/main.go +tests/benchmarks/vector-prepend/pds.a: tests/benchmarks/vector-prepend/pds.go +tests/benchmarks/vector-set/main.a: tests/benchmarks/vector-set/main.go +tests/benchmarks/vector-set/pds.a: tests/benchmarks/vector-set/pds.go tests/benchmarks/map-builder-delete/main.a: tests/benchmarks/map-builder-delete/main.go tests/benchmarks/map-builder-delete/pds.a: tests/benchmarks/map-builder-delete/pds.go tests/benchmarks/map-builder-set/main.a: tests/benchmarks/map-builder-set/main.go @@ -180,10 +180,10 @@ tests/benchmarks/sortedmap-iterator-forward/main.a: tests/benchmarks/sortedmap-i tests/benchmarks/sortedmap-iterator-forward/pds.a: tests/benchmarks/sortedmap-iterator-forward/pds.go tests/benchmarks/sortedmap-set/main.a: tests/benchmarks/sortedmap-set/main.go tests/benchmarks/sortedmap-set/pds.a: tests/benchmarks/sortedmap-set/pds.go -tests/functional/list-api/main.a: tests/functional/list-api/main.go -tests/functional/list-api/pds.a: tests/functional/list-api/pds.go -tests/functional/list-builder-api/main.a: tests/functional/list-builder-api/main.go -tests/functional/list-builder-api/pds.a: tests/functional/list-builder-api/pds.go +tests/functional/vector-api/main.a: tests/functional/vector-api/main.go +tests/functional/vector-api/pds.a: tests/functional/vector-api/pds.go +tests/functional/vector-builder-api/main.a: tests/functional/vector-builder-api/main.go +tests/functional/vector-builder-api/pds.a: tests/functional/vector-builder-api/pds.go tests/functional/map-api/main.a: tests/functional/map-api/main.go tests/functional/map-api/pds.a: tests/functional/map-api/pds.go tests/functional/map-builder-api/main.a: tests/functional/map-builder-api/main.go @@ -198,14 +198,14 @@ tests/benchmarks/builtin-map-delete/main.bin: tests/benchmarks/builtin-map-delet tests/benchmarks/builtin-map-set/main.bin: tests/benchmarks/builtin-map-set/main.a tests/benchmarks/builtin-slice-append-int/main.bin: tests/benchmarks/builtin-slice-append-int/main.a tests/benchmarks/builtin-slice-append-interface/main.bin: tests/benchmarks/builtin-slice-append-interface/main.a -tests/benchmarks/list-append/main.bin: tests/benchmarks/list-append/main.a -tests/benchmarks/list-builder-append/main.bin: tests/benchmarks/list-builder-append/main.a -tests/benchmarks/list-builder-prepend/main.bin: tests/benchmarks/list-builder-prepend/main.a -tests/benchmarks/list-builder-set/main.bin: tests/benchmarks/list-builder-set/main.a -tests/benchmarks/list-iterator-backward/main.bin: tests/benchmarks/list-iterator-backward/main.a -tests/benchmarks/list-iterator-forward/main.bin: tests/benchmarks/list-iterator-forward/main.a -tests/benchmarks/list-prepend/main.bin: tests/benchmarks/list-prepend/main.a -tests/benchmarks/list-set/main.bin: tests/benchmarks/list-set/main.a +tests/benchmarks/vector-append/main.bin: tests/benchmarks/vector-append/main.a +tests/benchmarks/vector-builder-append/main.bin: tests/benchmarks/vector-builder-append/main.a +tests/benchmarks/vector-builder-prepend/main.bin: tests/benchmarks/vector-builder-prepend/main.a +tests/benchmarks/vector-builder-set/main.bin: tests/benchmarks/vector-builder-set/main.a +tests/benchmarks/vector-iterator-backward/main.bin: tests/benchmarks/vector-iterator-backward/main.a +tests/benchmarks/vector-iterator-forward/main.bin: tests/benchmarks/vector-iterator-forward/main.a +tests/benchmarks/vector-prepend/main.bin: tests/benchmarks/vector-prepend/main.a +tests/benchmarks/vector-set/main.bin: tests/benchmarks/vector-set/main.a tests/benchmarks/map-builder-delete/main.bin: tests/benchmarks/map-builder-delete/main.a tests/benchmarks/map-builder-set/main.bin: tests/benchmarks/map-builder-set/main.a tests/benchmarks/map-delete/main.bin: tests/benchmarks/map-delete/main.a @@ -217,8 +217,8 @@ tests/benchmarks/sortedmap-delete/main.bin: tests/benchmarks/sortedmap-delete/ma tests/benchmarks/sortedmap-iterator-backward/main.bin: tests/benchmarks/sortedmap-iterator-backward/main.a tests/benchmarks/sortedmap-iterator-forward/main.bin: tests/benchmarks/sortedmap-iterator-forward/main.a tests/benchmarks/sortedmap-set/main.bin: tests/benchmarks/sortedmap-set/main.a -tests/functional/list-api/main.bin: tests/functional/list-api/main.a -tests/functional/list-builder-api/main.bin: tests/functional/list-builder-api/main.a +tests/functional/vector-api/main.bin: tests/functional/vector-api/main.a +tests/functional/vector-builder-api/main.bin: tests/functional/vector-builder-api/main.a tests/functional/map-api/main.bin: tests/functional/map-api/main.a tests/functional/map-builder-api/main.bin: tests/functional/map-builder-api/main.a tests/functional/sortedmap-api/main.bin: tests/functional/sortedmap-api/main.a @@ -228,14 +228,14 @@ tests/benchmarks/builtin-map-delete/main.bin-check: tests/benchmarks/builtin-map tests/benchmarks/builtin-map-set/main.bin-check: tests/benchmarks/builtin-map-set/main.bin tests/benchmarks/builtin-slice-append-int/main.bin-check: tests/benchmarks/builtin-slice-append-int/main.bin tests/benchmarks/builtin-slice-append-interface/main.bin-check: tests/benchmarks/builtin-slice-append-interface/main.bin -tests/benchmarks/list-append/main.bin-check: tests/benchmarks/list-append/main.bin -tests/benchmarks/list-builder-append/main.bin-check: tests/benchmarks/list-builder-append/main.bin -tests/benchmarks/list-builder-prepend/main.bin-check: tests/benchmarks/list-builder-prepend/main.bin -tests/benchmarks/list-builder-set/main.bin-check: tests/benchmarks/list-builder-set/main.bin -tests/benchmarks/list-iterator-backward/main.bin-check: tests/benchmarks/list-iterator-backward/main.bin -tests/benchmarks/list-iterator-forward/main.bin-check: tests/benchmarks/list-iterator-forward/main.bin -tests/benchmarks/list-prepend/main.bin-check: tests/benchmarks/list-prepend/main.bin -tests/benchmarks/list-set/main.bin-check: tests/benchmarks/list-set/main.bin +tests/benchmarks/vector-append/main.bin-check: tests/benchmarks/vector-append/main.bin +tests/benchmarks/vector-builder-append/main.bin-check: tests/benchmarks/vector-builder-append/main.bin +tests/benchmarks/vector-builder-prepend/main.bin-check: tests/benchmarks/vector-builder-prepend/main.bin +tests/benchmarks/vector-builder-set/main.bin-check: tests/benchmarks/vector-builder-set/main.bin +tests/benchmarks/vector-iterator-backward/main.bin-check: tests/benchmarks/vector-iterator-backward/main.bin +tests/benchmarks/vector-iterator-forward/main.bin-check: tests/benchmarks/vector-iterator-forward/main.bin +tests/benchmarks/vector-prepend/main.bin-check: tests/benchmarks/vector-prepend/main.bin +tests/benchmarks/vector-set/main.bin-check: tests/benchmarks/vector-set/main.bin tests/benchmarks/map-builder-delete/main.bin-check: tests/benchmarks/map-builder-delete/main.bin tests/benchmarks/map-builder-set/main.bin-check: tests/benchmarks/map-builder-set/main.bin tests/benchmarks/map-delete/main.bin-check: tests/benchmarks/map-delete/main.bin @@ -247,8 +247,8 @@ tests/benchmarks/sortedmap-delete/main.bin-check: tests/benchmarks/sortedmap-del tests/benchmarks/sortedmap-iterator-backward/main.bin-check: tests/benchmarks/sortedmap-iterator-backward/main.bin tests/benchmarks/sortedmap-iterator-forward/main.bin-check: tests/benchmarks/sortedmap-iterator-forward/main.bin tests/benchmarks/sortedmap-set/main.bin-check: tests/benchmarks/sortedmap-set/main.bin -tests/functional/list-api/main.bin-check: tests/functional/list-api/main.bin -tests/functional/list-builder-api/main.bin-check: tests/functional/list-builder-api/main.bin +tests/functional/vector-api/main.bin-check: tests/functional/vector-api/main.bin +tests/functional/vector-builder-api/main.bin-check: tests/functional/vector-builder-api/main.bin tests/functional/map-api/main.bin-check: tests/functional/map-api/main.bin tests/functional/map-builder-api/main.bin-check: tests/functional/map-builder-api/main.bin tests/functional/sortedmap-api/main.bin-check: tests/functional/sortedmap-api/main.bin @@ -258,14 +258,14 @@ tests/benchmarks/builtin-map-delete/main.a: tests/benchmarks/builtin-map-delete/ tests/benchmarks/builtin-map-set/main.a: tests/benchmarks/builtin-map-set/$(NAME).a tests/benchmarks/builtin-slice-append-int/main.a: tests/benchmarks/builtin-slice-append-int/$(NAME).a tests/benchmarks/builtin-slice-append-interface/main.a: tests/benchmarks/builtin-slice-append-interface/$(NAME).a -tests/benchmarks/list-append/main.a: tests/benchmarks/list-append/$(NAME).a -tests/benchmarks/list-builder-append/main.a: tests/benchmarks/list-builder-append/$(NAME).a -tests/benchmarks/list-builder-prepend/main.a: tests/benchmarks/list-builder-prepend/$(NAME).a -tests/benchmarks/list-builder-set/main.a: tests/benchmarks/list-builder-set/$(NAME).a -tests/benchmarks/list-iterator-backward/main.a: tests/benchmarks/list-iterator-backward/$(NAME).a -tests/benchmarks/list-iterator-forward/main.a: tests/benchmarks/list-iterator-forward/$(NAME).a -tests/benchmarks/list-prepend/main.a: tests/benchmarks/list-prepend/$(NAME).a -tests/benchmarks/list-set/main.a: tests/benchmarks/list-set/$(NAME).a +tests/benchmarks/vector-append/main.a: tests/benchmarks/vector-append/$(NAME).a +tests/benchmarks/vector-builder-append/main.a: tests/benchmarks/vector-builder-append/$(NAME).a +tests/benchmarks/vector-builder-prepend/main.a: tests/benchmarks/vector-builder-prepend/$(NAME).a +tests/benchmarks/vector-builder-set/main.a: tests/benchmarks/vector-builder-set/$(NAME).a +tests/benchmarks/vector-iterator-backward/main.a: tests/benchmarks/vector-iterator-backward/$(NAME).a +tests/benchmarks/vector-iterator-forward/main.a: tests/benchmarks/vector-iterator-forward/$(NAME).a +tests/benchmarks/vector-prepend/main.a: tests/benchmarks/vector-prepend/$(NAME).a +tests/benchmarks/vector-set/main.a: tests/benchmarks/vector-set/$(NAME).a tests/benchmarks/map-builder-delete/main.a: tests/benchmarks/map-builder-delete/$(NAME).a tests/benchmarks/map-builder-set/main.a: tests/benchmarks/map-builder-set/$(NAME).a tests/benchmarks/map-delete/main.a: tests/benchmarks/map-delete/$(NAME).a @@ -277,8 +277,8 @@ tests/benchmarks/sortedmap-delete/main.a: tests/benchmarks/sortedmap-delete/$(NA tests/benchmarks/sortedmap-iterator-backward/main.a: tests/benchmarks/sortedmap-iterator-backward/$(NAME).a tests/benchmarks/sortedmap-iterator-forward/main.a: tests/benchmarks/sortedmap-iterator-forward/$(NAME).a tests/benchmarks/sortedmap-set/main.a: tests/benchmarks/sortedmap-set/$(NAME).a -tests/functional/list-api/main.a: tests/functional/list-api/$(NAME).a -tests/functional/list-builder-api/main.a: tests/functional/list-builder-api/$(NAME).a +tests/functional/vector-api/main.a: tests/functional/vector-api/$(NAME).a +tests/functional/vector-builder-api/main.a: tests/functional/vector-builder-api/$(NAME).a tests/functional/map-api/main.a: tests/functional/map-api/$(NAME).a tests/functional/map-builder-api/main.a: tests/functional/map-builder-api/$(NAME).a tests/functional/sortedmap-api/main.a: tests/functional/sortedmap-api/$(NAME).a @@ -4,7 +4,7 @@ // // Immutable collections provide an efficient, safe way to share collections // of data while minimizing locks. The collections in this package provide -// List, Map, and SortedMap implementations. These act similarly to slices +// Vector, Map, and SortedMap implementations. These act similarly to slices // and maps, respectively, except that altering a collection returns a new // copy of the collection with that change. // @@ -16,9 +16,9 @@ // // # Collection Types // -// The List type provides an API similar to Go slices. They allow appending, +// The Vector type provides an API similar to Go slices. They allow appending, // prepending, and updating of elements. Elements can also be fetched by index -// or iterated over using a ListIterator. +// or iterated over using a VectorIterator. // // The Map & SortedMap types provide an API similar to Go maps. They allow // values to be assigned to unique keys and allow for the deletion of keys. @@ -50,20 +50,20 @@ import ( "strings" ) -// List is a dense, ordered, indexed collections. They are analogous to slices -// in Go. They can be updated by appending to the end of the list, prepending -// values to the beginning of the list, or updating existing indexes in the -// list. -type List[T any] struct { - root listNode[T] // root node +// Vector is a dense, ordered, indexed collections. They are analogous to slices +// in Go. They can be updated by appending to the end of the vector, prepending +// values to the beginning of the vector, or updating existing indexes in the +// vector. +type Vector[T any] struct { + root vectorNode[T] // root node origin int // offset to zero index element size int // total number of elements in use } -// NewList returns a new empty instance of List. -func NewList[T any](values ...T) *List[T] { - l := &List[T]{ - root: &listLeafNode[T]{}, +// NewVector returns a new empty instance of Vector. +func NewVector[T any](values ...T) *Vector[T] { + l := &Vector[T]{ + root: &vectorLeafNode[T]{}, } for _, value := range values { l.append(value, true) @@ -71,41 +71,47 @@ func NewList[T any](values ...T) *List[T] { return l } -// clone returns a copy of the list. -func (l *List[T]) clone() *List[T] { +// clone returns a copy of the vector. +func (l *Vector[T]) clone() *Vector[T] { other := *l return &other } -// Len returns the number of elements in the list. -func (l *List[T]) Len() int { +// Len returns the number of elements in the vector. +func (l *Vector[T]) Len() int { return l.size } // cap returns the total number of possible elements for the current depth. -func (l *List[T]) cap() int { - return 1 << (l.root.depth() * listNodeBits) +func (l *Vector[T]) cap() int { + return 1 << (l.root.depth() * vectorNodeBits) } // Get returns the value at the given index. Similar to slices, this method will -// panic if index is below zero or is greater than or equal to the list size. -func (l *List[T]) Get(index int) T { +// panic if index is below zero or is greater than or equal to the vector size. +func (l *Vector[T]) Get(index int) T { if index < 0 || index >= l.size { - panic(fmt.Sprintf("immutable.List.Get: index %d out of bounds", index)) + panic(fmt.Sprintf( + "immutable.Vector.Get: index %d out of bounds", + index, + )) } return l.root.get(l.origin + index) } -// Set returns a new list with value set at index. Similar to slices, this +// Set returns a new vector with value set at index. Similar to slices, this // method will panic if index is below zero or if the index is greater than -// or equal to the list size. -func (l *List[T]) Set(index int, value T) *List[T] { +// or equal to the vector size. +func (l *Vector[T]) Set(index int, value T) *Vector[T] { return l.set(index, value, false) } -func (l *List[T]) set(index int, value T, mutable bool) *List[T] { +func (l *Vector[T]) set(index int, value T, mutable bool) *Vector[T] { if index < 0 || index >= l.size { - panic(fmt.Sprintf("immutable.List.Set: index %d out of bounds", index)) + panic(fmt.Sprintf( + "immutable.Vector.Set: index %d out of bounds", + index, + )) } other := l if !mutable { @@ -115,20 +121,20 @@ func (l *List[T]) set(index int, value T, mutable bool) *List[T] { return other } -// Append returns a new list with value added to the end of the list. -func (l *List[T]) Append(value T) *List[T] { +// Append returns a new vector with value added to the end of the vector. +func (l *Vector[T]) Append(value T) *Vector[T] { return l.append(value, false) } -func (l *List[T]) append(value T, mutable bool) *List[T] { +func (l *Vector[T]) append(value T, mutable bool) *Vector[T] { other := l if !mutable { other = l.clone() } - // Expand list to the right if no slots remain. + // Expand vector to the right if no slots remain. if other.size+other.origin >= l.cap() { - newRoot := &listBranchNode[T]{d: other.root.depth() + 1} + newRoot := &vectorBranchNode[T]{d: other.root.depth() + 1} newRoot.children[0] = other.root other.root = newRoot } @@ -139,23 +145,25 @@ func (l *List[T]) append(value T, mutable bool) *List[T] { return other } -// Prepend returns a new list with value(s) added to the beginning of the list. -func (l *List[T]) Prepend(value T) *List[T] { +// Prepend returns a new vector with value(s) added to the beginning of the +// vector. +func (l *Vector[T]) Prepend(value T) *Vector[T] { return l.prepend(value, false) } -func (l *List[T]) prepend(value T, mutable bool) *List[T] { +func (l *Vector[T]) prepend(value T, mutable bool) *Vector[T] { other := l if !mutable { other = l.clone() } - // Expand list to the left if no slots remain. + // Expand vector to the left if no slots remain. if other.origin == 0 { - newRoot := &listBranchNode[T]{d: other.root.depth() + 1} - newRoot.children[listNodeSize-1] = other.root + newRoot := &vectorBranchNode[T]{d: other.root.depth() + 1} + newRoot.children[vectorNodeSize-1] = other.root other.root = newRoot - other.origin += (listNodeSize - 1) << (other.root.depth() * listNodeBits) + other.origin += (vectorNodeSize - 1) << + ((other.root.depth() * vectorNodeBits)) } // Increase size and move origin back. Update first element to value. @@ -165,28 +173,31 @@ func (l *List[T]) prepend(value T, mutable bool) *List[T] { return other } -// Slice returns a new list of elements between start index and end index. +// Slice returns a new vector of elements between start index and end index. // Similar to slices, this method will panic if start or end are below zero or -// greater than the list size. A panic will also occur if start is greater than -// end. +// greater than the vector size. A panic will also occur if start is greater +// than end. // // Unlike Go slices, references to inaccessible elements will be automatically // removed so they can be garbage collected. -func (l *List[T]) Slice(start, end int) *List[T] { +func (l *Vector[T]) Slice(start, end int) *Vector[T] { return l.slice(start, end, false) } -func (l *List[T]) slice(start, end int, mutable bool) *List[T] { +func (l *Vector[T]) slice(start, end int, mutable bool) *Vector[T] { // Panics similar to Go slices. if start < 0 || start > l.size { - panic(fmt.Sprintf("immutable.List.Slice: start index %d out of bounds", start)) + panic(fmt.Sprintf( + "immutable.Vector.Slice: start index %d out of bounds", + start, + )) } else if end < 0 || end > l.size { - panic(fmt.Sprintf("immutable.List.Slice: end index %d out of bounds", end)) + panic(fmt.Sprintf("immutable.Vector.Slice: end index %d out of bounds", end)) } else if start > end { - panic(fmt.Sprintf("immutable.List.Slice: invalid slice index: [%d:%d]", start, end)) + panic(fmt.Sprintf("immutable.Vector.Slice: invalid slice index: [%d:%d]", start, end)) } - // Return the same list if the start and end are the entire range. + // Return the same vector if the start and end are the entire range. if start == 0 && end == l.size { return l } @@ -203,15 +214,16 @@ func (l *List[T]) slice(start, end int, mutable bool) *List[T] { // Contract tree while the start & end are in the same child node. for other.root.depth() > 1 { - i := (other.origin >> (other.root.depth() * listNodeBits)) & listNodeMask - j := ((other.origin + other.size - 1) >> (other.root.depth() * listNodeBits)) & listNodeMask + i := (other.origin >> (other.root.depth() * vectorNodeBits)) & vectorNodeMask + j := ((other.origin + other.size - 1) >> (other.root.depth() * vectorNodeBits)) & vectorNodeMask if i != j { break // branch contains at least two nodes, exit } - // Replace the current root with the single child & update origin offset. - other.origin -= i << (other.root.depth() * listNodeBits) - other.root = other.root.(*listBranchNode[T]).children[i] + // Replace the current root with the single child & update + // origin offset. + other.origin -= i << (other.root.depth() * vectorNodeBits) + other.root = other.root.(*vectorBranchNode[T]).children[i] } // Ensure all references are removed before start & after end. @@ -221,133 +233,138 @@ func (l *List[T]) slice(start, end int, mutable bool) *List[T] { return other } -// Iterator returns a new iterator for this list positioned at the first index. -func (l *List[T]) Iterator() *ListIterator[T] { - itr := &ListIterator[T]{list: l} +// Iterator returns a new iterator for this vector positioned at the first +// index. +func (l *Vector[T]) Iterator() *VectorIterator[T] { + itr := &VectorIterator[T]{vector: l} itr.First() return itr } -// ListBuilder represents an efficient builder for creating new Lists. -type ListBuilder[T any] struct { - list *List[T] // current state +// VectorBuilder represents an efficient builder for creating new Vectors. +type VectorBuilder[T any] struct { + vector *Vector[T] // current state } -// NewListBuilder returns a new instance of ListBuilder. -func NewListBuilder[T any]() *ListBuilder[T] { - return &ListBuilder[T]{list: NewList[T]()} +// NewVectorBuilder returns a new instance of VectorBuilder. +func NewVectorBuilder[T any]() *VectorBuilder[T] { + return &VectorBuilder[T]{vector: NewVector[T]()} } -// List returns the current copy of the list. -// The builder should not be used again after the list after this call. -func (b *ListBuilder[T]) List() *List[T] { - assert(b.list != nil, "immutable.ListBuilder.List(): duplicate call to fetch list") - list := b.list - b.list = nil - return list +// Vector returns the current copy of the vector. +// The builder should not be used again after the vector after this call. +func (b *VectorBuilder[T]) Vector() *Vector[T] { + assert(b.vector != nil, "immutable.VectorBuilder.Vector(): duplicate call to fetch vector") + vector := b.vector + b.vector = nil + return vector } -// Len returns the number of elements in the underlying list. -func (b *ListBuilder[T]) Len() int { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - return b.list.Len() +// Len returns the number of elements in the underlying vector. +func (b *VectorBuilder[T]) Len() int { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + return b.vector.Len() } // Get returns the value at the given index. Similar to slices, this method will -// panic if index is below zero or is greater than or equal to the list size. -func (b *ListBuilder[T]) Get(index int) T { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - return b.list.Get(index) +// panic if index is below zero or is greater than or equal to the vector size. +func (b *VectorBuilder[T]) Get(index int) T { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + return b.vector.Get(index) } // Set updates the value at the given index. Similar to slices, this method will // panic if index is below zero or if the index is greater than or equal to the -// list size. -func (b *ListBuilder[T]) Set(index int, value T) { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - b.list = b.list.set(index, value, true) +// vector size. +func (b *VectorBuilder[T]) Set(index int, value T) { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + b.vector = b.vector.set(index, value, true) } -// Append adds value to the end of the list. -func (b *ListBuilder[T]) Append(value T) { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - b.list = b.list.append(value, true) +// Append adds value to the end of the vector. +func (b *VectorBuilder[T]) Append(value T) { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + b.vector = b.vector.append(value, true) } -// Prepend adds value to the beginning of the list. -func (b *ListBuilder[T]) Prepend(value T) { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - b.list = b.list.prepend(value, true) +// Prepend adds value to the beginning of the vector. +func (b *VectorBuilder[T]) Prepend(value T) { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + b.vector = b.vector.prepend(value, true) } -// Slice updates the list with a sublist of elements between start and end index. -// See List.Slice() for more details. -func (b *ListBuilder[T]) Slice(start, end int) { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - b.list = b.list.slice(start, end, true) +// Slice updates the vector with a subvector of elements between start and end +// index. +// See Vector.Slice() for more details. +func (b *VectorBuilder[T]) Slice(start, end int) { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + b.vector = b.vector.slice(start, end, true) } -// Iterator returns a new iterator for the underlying list. -func (b *ListBuilder[T]) Iterator() *ListIterator[T] { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - return b.list.Iterator() +// Iterator returns a new iterator for the underlying vector. +func (b *VectorBuilder[T]) Iterator() *VectorIterator[T] { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + return b.vector.Iterator() } -// Constants for bit shifts used for levels in the List trie. +// Constants for bit shifts used for levels in the Vector trie. const ( - listNodeBits = 5 - listNodeSize = 1 << listNodeBits - listNodeMask = listNodeSize - 1 + vectorNodeBits = 5 + vectorNodeSize = 1 << vectorNodeBits + vectorNodeMask = vectorNodeSize - 1 ) -// listNode represents either a branch or leaf node in a List. -type listNode[T any] interface { +// vectorNode represents either a branch or leaf node in a Vector. +type vectorNode[T any] interface { depth() uint get(index int) T - set(index int, v T, mutable bool) listNode[T] + set(index int, v T, mutable bool) vectorNode[T] containsBefore(index int) bool containsAfter(index int) bool - deleteBefore(index int, mutable bool) listNode[T] - deleteAfter(index int, mutable bool) listNode[T] + deleteBefore(index int, mutable bool) vectorNode[T] + deleteAfter(index int, mutable bool) vectorNode[T] } -// newListNode returns a leaf node for depth zero, otherwise returns a branch node. -func newListNode[T any](depth uint) listNode[T] { +// newVectorNode returns a leaf node for depth zero, otherwise returns a branch +// node. +func newVectorNode[T any](depth uint) vectorNode[T] { if depth == 0 { - return &listLeafNode[T]{} + return &vectorLeafNode[T]{} } - return &listBranchNode[T]{d: depth} + return &vectorBranchNode[T]{d: depth} } -// listBranchNode represents a branch of a List tree at a given depth. -type listBranchNode[T any] struct { +// vectorBranchNode represents a branch of a Vector tree at a given depth. +type vectorBranchNode[T any] struct { d uint // depth - children [listNodeSize]listNode[T] + children [vectorNodeSize]vectorNode[T] } // depth returns the depth of this branch node from the leaf. -func (n *listBranchNode[T]) depth() uint { return n.d } +func (n *vectorBranchNode[T]) depth() uint { return n.d } // get returns the child node at the segment of the index for this depth. -func (n *listBranchNode[T]) get(index int) T { - idx := (index >> (n.d * listNodeBits)) & listNodeMask +func (n *vectorBranchNode[T]) get(index int) T { + idx := (index >> (n.d * vectorNodeBits)) & vectorNodeMask return n.children[idx].get(index) } -// set recursively updates the value at index for each lower depth from the node. -func (n *listBranchNode[T]) set(index int, v T, mutable bool) listNode[T] { - idx := (index >> (n.d * listNodeBits)) & listNodeMask +// set recursively updates the value at index for each lower depth from the +// node. +func (n *vectorBranchNode[T]) set(index int, v T, mutable bool) vectorNode[T] { + idx := (index >> (n.d * vectorNodeBits)) & vectorNodeMask - // Find child for the given value in the branch. Create new if it doesn't exist. + // Find child for the given value in the branch. Create new if it + // doesn't exist. child := n.children[idx] if child == nil { - child = newListNode[T](n.depth() - 1) + child = newVectorNode[T](n.depth() - 1) } // Return a copy of this branch with the new child. - var other *listBranchNode[T] + var other *vectorBranchNode[T] if mutable { other = n } else { @@ -359,8 +376,8 @@ func (n *listBranchNode[T]) set(index int, v T, mutable bool) listNode[T] { } // containsBefore returns true if non-nil values exists between [0,index). -func (n *listBranchNode[T]) containsBefore(index int) bool { - idx := (index >> (n.d * listNodeBits)) & listNodeMask +func (n *vectorBranchNode[T]) containsBefore(index int) bool { + idx := (index >> (n.d * vectorNodeBits)) & vectorNodeMask // Quickly check if any direct children exist before this segment of the index. for i := 0; i < idx; i++ { @@ -376,9 +393,9 @@ func (n *listBranchNode[T]) containsBefore(index int) bool { return false } -// containsAfter returns true if non-nil values exists between (index,listNodeSize). -func (n *listBranchNode[T]) containsAfter(index int) bool { - idx := (index >> (n.d * listNodeBits)) & listNodeMask +// containsAfter returns true if non-nil values exists between (index,vectorNodeSize). +func (n *vectorBranchNode[T]) containsAfter(index int) bool { + idx := (index >> (n.d * vectorNodeBits)) & vectorNodeMask // Quickly check if any direct children exist after this segment of the index. for i := idx + 1; i < len(n.children); i++ { @@ -395,23 +412,23 @@ func (n *listBranchNode[T]) containsAfter(index int) bool { } // deleteBefore returns a new node with all elements before index removed. -func (n *listBranchNode[T]) deleteBefore(index int, mutable bool) listNode[T] { +func (n *vectorBranchNode[T]) deleteBefore(index int, mutable bool) vectorNode[T] { // Ignore if no nodes exist before the given index. if !n.containsBefore(index) { return n } // Return a copy with any nodes prior to the index removed. - idx := (index >> (n.d * listNodeBits)) & listNodeMask + idx := (index >> (n.d * vectorNodeBits)) & vectorNodeMask - var other *listBranchNode[T] + var other *vectorBranchNode[T] if mutable { other = n for i := 0; i < idx; i++ { n.children[i] = nil } } else { - other = &listBranchNode[T]{d: n.d} + other = &vectorBranchNode[T]{d: n.d} copy(other.children[idx:][:], n.children[idx:][:]) } @@ -422,23 +439,23 @@ func (n *listBranchNode[T]) deleteBefore(index int, mutable bool) listNode[T] { } // deleteBefore returns a new node with all elements before index removed. -func (n *listBranchNode[T]) deleteAfter(index int, mutable bool) listNode[T] { +func (n *vectorBranchNode[T]) deleteAfter(index int, mutable bool) vectorNode[T] { // Ignore if no nodes exist after the given index. if !n.containsAfter(index) { return n } // Return a copy with any nodes after the index removed. - idx := (index >> (n.d * listNodeBits)) & listNodeMask + idx := (index >> (n.d * vectorNodeBits)) & vectorNodeMask - var other *listBranchNode[T] + var other *vectorBranchNode[T] if mutable { other = n for i := idx + 1; i < len(n.children); i++ { n.children[i] = nil } } else { - other = &listBranchNode[T]{d: n.d} + other = &vectorBranchNode[T]{d: n.d} copy(other.children[:idx+1], n.children[:idx+1]) } @@ -448,25 +465,25 @@ func (n *listBranchNode[T]) deleteAfter(index int, mutable bool) listNode[T] { return other } -// listLeafNode represents a leaf node in a List. -type listLeafNode[T any] struct { - children [listNodeSize]T +// vectorLeafNode represents a leaf node in a Vector. +type vectorLeafNode[T any] struct { + children [vectorNodeSize]T // bitset with ones at occupied positions, position 0 is the LSB occupied uint32 } // depth always returns 0 for leaf nodes. -func (n *listLeafNode[T]) depth() uint { return 0 } +func (n *vectorLeafNode[T]) depth() uint { return 0 } // get returns the value at the given index. -func (n *listLeafNode[T]) get(index int) T { - return n.children[index&listNodeMask] +func (n *vectorLeafNode[T]) get(index int) T { + return n.children[index&vectorNodeMask] } // set returns a copy of the node with the value at the index updated to v. -func (n *listLeafNode[T]) set(index int, v T, mutable bool) listNode[T] { - idx := index & listNodeMask - var other *listLeafNode[T] +func (n *vectorLeafNode[T]) set(index int, v T, mutable bool) vectorNode[T] { + idx := index & vectorNodeMask + var other *vectorLeafNode[T] if mutable { other = n } else { @@ -479,26 +496,26 @@ func (n *listLeafNode[T]) set(index int, v T, mutable bool) listNode[T] { } // containsBefore returns true if non-nil values exists between [0,index). -func (n *listLeafNode[T]) containsBefore(index int) bool { - idx := index & listNodeMask +func (n *vectorLeafNode[T]) containsBefore(index int) bool { + idx := index & vectorNodeMask return bits.TrailingZeros32(n.occupied) < idx } -// containsAfter returns true if non-nil values exists between (index,listNodeSize). -func (n *listLeafNode[T]) containsAfter(index int) bool { - idx := index & listNodeMask +// containsAfter returns true if non-nil values exists between (index,vectorNodeSize). +func (n *vectorLeafNode[T]) containsAfter(index int) bool { + idx := index & vectorNodeMask lastSetPos := 31 - bits.LeadingZeros32(n.occupied) return lastSetPos > idx } // deleteBefore returns a new node with all elements before index removed. -func (n *listLeafNode[T]) deleteBefore(index int, mutable bool) listNode[T] { +func (n *vectorLeafNode[T]) deleteBefore(index int, mutable bool) vectorNode[T] { if !n.containsBefore(index) { return n } - idx := index & listNodeMask - var other *listLeafNode[T] + idx := index & vectorNodeMask + var other *vectorLeafNode[T] if mutable { other = n var empty T @@ -506,7 +523,7 @@ func (n *listLeafNode[T]) deleteBefore(index int, mutable bool) listNode[T] { other.children[i] = empty } } else { - other = &listLeafNode[T]{occupied: n.occupied} + other = &vectorLeafNode[T]{occupied: n.occupied} copy(other.children[idx:][:], n.children[idx:][:]) } // Set the first idx bits to 0. @@ -515,13 +532,13 @@ func (n *listLeafNode[T]) deleteBefore(index int, mutable bool) listNode[T] { } // deleteAfter returns a new node with all elements after index removed. -func (n *listLeafNode[T]) deleteAfter(index int, mutable bool) listNode[T] { +func (n *vectorLeafNode[T]) deleteAfter(index int, mutable bool) vectorNode[T] { if !n.containsAfter(index) { return n } - idx := index & listNodeMask - var other *listLeafNode[T] + idx := index & vectorNodeMask + var other *vectorLeafNode[T] if mutable { other = n var empty T @@ -529,7 +546,7 @@ func (n *listLeafNode[T]) deleteAfter(index int, mutable bool) listNode[T] { other.children[i] = empty } } else { - other = &listLeafNode[T]{occupied: n.occupied} + other = &vectorLeafNode[T]{occupied: n.occupied} copy(other.children[:idx+1][:], n.children[:idx+1][:]) } // Set bits after idx to 0. idx < 31 because n.containsAfter(index) == true. @@ -537,55 +554,55 @@ func (n *listLeafNode[T]) deleteAfter(index int, mutable bool) listNode[T] { return other } -// ListIterator represents an ordered iterator over a list. -type ListIterator[T any] struct { - list *List[T] // source list +// VectorIterator represents an ordered iterator over a vector. +type VectorIterator[T any] struct { + vector *Vector[T] // source vector index int // current index position - stack [32]listIteratorElem[T] // search stack + stack [32]vectorIteratorElem[T] // search stack depth int // stack depth } // Done returns true if no more elements remain in the iterator. -func (itr *ListIterator[T]) Done() bool { - return itr.index < 0 || itr.index >= itr.list.Len() +func (itr *VectorIterator[T]) Done() bool { + return itr.index < 0 || itr.index >= itr.vector.Len() } // First positions the iterator on the first index. -// If source list is empty then no change is made. -func (itr *ListIterator[T]) First() { - if itr.list.Len() != 0 { +// If source vector is empty then no change is made. +func (itr *VectorIterator[T]) First() { + if itr.vector.Len() != 0 { itr.Seek(0) } } // Last positions the iterator on the last index. -// If source list is empty then no change is made. -func (itr *ListIterator[T]) Last() { - if n := itr.list.Len(); n != 0 { +// If source vector is empty then no change is made. +func (itr *VectorIterator[T]) Last() { + if n := itr.vector.Len(); n != 0 { itr.Seek(n - 1) } } -// Seek moves the iterator position to the given index in the list. +// Seek moves the iterator position to the given index in the vector. // Similar to Go slices, this method will panic if index is below zero or if -// the index is greater than or equal to the list size. -func (itr *ListIterator[T]) Seek(index int) { +// the index is greater than or equal to the vector size. +func (itr *VectorIterator[T]) Seek(index int) { // Panic similar to Go slices. - if index < 0 || index >= itr.list.Len() { - panic(fmt.Sprintf("immutable.ListIterator.Seek: index %d out of bounds", index)) + if index < 0 || index >= itr.vector.Len() { + panic(fmt.Sprintf("immutable.VectorIterator.Seek: index %d out of bounds", index)) } itr.index = index // Reset to the bottom of the stack at seek to the correct position. - itr.stack[0] = listIteratorElem[T]{node: itr.list.root} + itr.stack[0] = vectorIteratorElem[T]{node: itr.vector.root} itr.depth = 0 itr.seek(index) } // Next returns the current index and its value & moves the iterator forward. // Returns an index of -1 if the there are no more elements to return. -func (itr *ListIterator[T]) Next() (index int, value T) { +func (itr *VectorIterator[T]) Next() (index int, value T) { // Exit immediately if there are no elements remaining. var empty T if itr.Done() { @@ -594,7 +611,7 @@ func (itr *ListIterator[T]) Next() (index int, value T) { // Retrieve current index & value. elem := &itr.stack[itr.depth] - index, value = itr.index, elem.node.(*listLeafNode[T]).children[elem.index] + index, value = itr.index, elem.node.(*vectorLeafNode[T]).children[elem.index] // Increase index. If index is at the end then return immediately. itr.index++ @@ -603,7 +620,7 @@ func (itr *ListIterator[T]) Next() (index int, value T) { } // Move up stack until we find a node that has remaining position ahead. - for ; itr.depth > 0 && itr.stack[itr.depth].index >= listNodeSize-1; itr.depth-- { + for ; itr.depth > 0 && itr.stack[itr.depth].index >= vectorNodeSize-1; itr.depth-- { } // Seek to correct position from current depth. @@ -614,7 +631,7 @@ func (itr *ListIterator[T]) Next() (index int, value T) { // Prev returns the current index and value and moves the iterator backward. // Returns an index of -1 if the there are no more elements to return. -func (itr *ListIterator[T]) Prev() (index int, value T) { +func (itr *VectorIterator[T]) Prev() (index int, value T) { // Exit immediately if there are no elements remaining. var empty T if itr.Done() { @@ -623,7 +640,7 @@ func (itr *ListIterator[T]) Prev() (index int, value T) { // Retrieve current index & value. elem := &itr.stack[itr.depth] - index, value = itr.index, elem.node.(*listLeafNode[T]).children[elem.index] + index, value = itr.index, elem.node.(*vectorLeafNode[T]).children[elem.index] // Decrease index. If index is past the beginning then return immediately. itr.index-- @@ -643,26 +660,26 @@ func (itr *ListIterator[T]) Prev() (index int, value T) { // seek positions the stack to the given index from the current depth. // Elements and indexes below the current depth are assumed to be correct. -func (itr *ListIterator[T]) seek(index int) { +func (itr *VectorIterator[T]) seek(index int) { // Iterate over each level until we reach a leaf node. for { elem := &itr.stack[itr.depth] - elem.index = ((itr.list.origin + index) >> (elem.node.depth() * listNodeBits)) & listNodeMask + elem.index = ((itr.vector.origin + index) >> (elem.node.depth() * vectorNodeBits)) & vectorNodeMask switch node := elem.node.(type) { - case *listBranchNode[T]: + case *vectorBranchNode[T]: child := node.children[elem.index] - itr.stack[itr.depth+1] = listIteratorElem[T]{node: child} + itr.stack[itr.depth+1] = vectorIteratorElem[T]{node: child} itr.depth++ - case *listLeafNode[T]: + case *vectorLeafNode[T]: return } } } -// listIteratorElem represents the node and it's child index within the stack. -type listIteratorElem[T any] struct { - node listNode[T] +// vectorIteratorElem represents the node and it's child index within the stack. +type vectorIteratorElem[T any] struct { + node vectorNode[T] index int } @@ -940,7 +957,7 @@ func (n *mapArrayNode[K, V]) set(key K, value V, shift uint, keyHash uint32, h H } // Update existing entry if a match is found. - // Otherwise append to the end of the element list if it doesn't exist. + // Otherwise append to the end of the element vector if it doesn't exist. var other mapArrayNode[K, V] if idx != -1 { other.entries = make([]mapEntry[K, V], len(n.entries)) @@ -1059,7 +1076,7 @@ func (n *mapBitmapIndexedNode[K, V]) set(key K, value V, shift uint, keyHash uin } // If node exists at given slot then overwrite it with new node. - // Otherwise expand the node list and insert new node into appropriate position. + // Otherwise expand the node vector and insert new node into appropriate position. other := &mapBitmapIndexedNode[K, V]{bitmap: n.bitmap | bit} if exists { other.nodes = make([]mapNode[K, V], len(n.nodes)) @@ -1113,7 +1130,7 @@ func (n *mapBitmapIndexedNode[K, V]) delete(key K, shift uint, keyHash uint32, h return n } - // Return copy with bit removed from bitmap and node removed from node list. + // Return copy with bit removed from bitmap and node removed from node vector. other := &mapBitmapIndexedNode[K, V]{bitmap: n.bitmap ^ bit, nodes: make([]mapNode[K, V], len(n.nodes)-1)} copy(other.nodes[:idx], n.nodes[:idx]) copy(other.nodes[idx:], n.nodes[idx+1:]) @@ -2691,7 +2708,7 @@ func (s SortedSetBuilder[T]) Len() int { } // SortedSet returns the current copy of the set. -// The builder should not be used again after the list after this call. +// The builder should not be used again after the vector after this call. func (s SortedSetBuilder[T]) SortedSet() SortedSet[T] { assert(s.s != nil, "immutable.SortedSetBuilder.SortedSet(): duplicate call to fetch sorted set") set := s.s diff --git a/tests/benchmarks/list-append/main.go b/tests/benchmarks/vector-append/main.go index f67563d..f67563d 120000 --- a/tests/benchmarks/list-append/main.go +++ b/tests/benchmarks/vector-append/main.go diff --git a/tests/benchmarks/list-append/pds.go b/tests/benchmarks/vector-append/pds.go index a9b7690..58368b3 100644 --- a/tests/benchmarks/list-append/pds.go +++ b/tests/benchmarks/vector-append/pds.go @@ -16,7 +16,7 @@ func MainTest() { flag.Parse() n := *nFlag - l := NewList[int]() + l := NewVector[int]() for i := 0; i < n; i++ { l = l.Append(i) } diff --git a/tests/benchmarks/list-builder-append/main.go b/tests/benchmarks/vector-builder-append/main.go index f67563d..f67563d 120000 --- a/tests/benchmarks/list-builder-append/main.go +++ b/tests/benchmarks/vector-builder-append/main.go diff --git a/tests/benchmarks/list-builder-append/pds.go b/tests/benchmarks/vector-builder-append/pds.go index 3357ee6..ab5cdec 100644 --- a/tests/benchmarks/list-builder-append/pds.go +++ b/tests/benchmarks/vector-builder-append/pds.go @@ -16,7 +16,7 @@ func MainTest() { flag.Parse() n := *nFlag - builder := NewListBuilder[int]() + builder := NewVectorBuilder[int]() for i := 0; i < n; i++ { builder.Append(i) } diff --git a/tests/benchmarks/list-builder-prepend/main.go b/tests/benchmarks/vector-builder-prepend/main.go index f67563d..f67563d 120000 --- a/tests/benchmarks/list-builder-prepend/main.go +++ b/tests/benchmarks/vector-builder-prepend/main.go diff --git a/tests/benchmarks/list-builder-prepend/pds.go b/tests/benchmarks/vector-builder-prepend/pds.go index 572b6b6..9d1d669 100644 --- a/tests/benchmarks/list-builder-prepend/pds.go +++ b/tests/benchmarks/vector-builder-prepend/pds.go @@ -16,7 +16,7 @@ func MainTest() { flag.Parse() n := *nFlag - builder := NewListBuilder[int]() + builder := NewVectorBuilder[int]() for i := 0; i < n; i++ { builder.Prepend(i) } diff --git a/tests/benchmarks/list-builder-set/main.go b/tests/benchmarks/vector-builder-set/main.go index f67563d..f67563d 120000 --- a/tests/benchmarks/list-builder-set/main.go +++ b/tests/benchmarks/vector-builder-set/main.go diff --git a/tests/benchmarks/list-builder-set/pds.go b/tests/benchmarks/vector-builder-set/pds.go index 4080e22..c4d5b2b 100644 --- a/tests/benchmarks/list-builder-set/pds.go +++ b/tests/benchmarks/vector-builder-set/pds.go @@ -16,7 +16,7 @@ func MainTest() { flag.Parse() n := *nFlag - builder := NewListBuilder[int]() + builder := NewVectorBuilder[int]() for i := 0; i < n; i++ { builder.Append(i) } diff --git a/tests/benchmarks/list-iterator-backward/main.go b/tests/benchmarks/vector-iterator-backward/main.go index f67563d..f67563d 120000 --- a/tests/benchmarks/list-iterator-backward/main.go +++ b/tests/benchmarks/vector-iterator-backward/main.go diff --git a/tests/benchmarks/list-iterator-backward/pds.go b/tests/benchmarks/vector-iterator-backward/pds.go index 6ca51e4..a03e138 100644 --- a/tests/benchmarks/list-iterator-backward/pds.go +++ b/tests/benchmarks/vector-iterator-backward/pds.go @@ -16,7 +16,7 @@ func MainTest() { flag.Parse() n := *nFlag - l := NewList[int]() + l := NewVector[int]() for i := 0; i < n; i++ { l = l.Append(i) } diff --git a/tests/benchmarks/list-iterator-forward/main.go b/tests/benchmarks/vector-iterator-forward/main.go index f67563d..f67563d 120000 --- a/tests/benchmarks/list-iterator-forward/main.go +++ b/tests/benchmarks/vector-iterator-forward/main.go diff --git a/tests/benchmarks/list-iterator-forward/pds.go b/tests/benchmarks/vector-iterator-forward/pds.go index 6831dad..298fd4e 100644 --- a/tests/benchmarks/list-iterator-forward/pds.go +++ b/tests/benchmarks/vector-iterator-forward/pds.go @@ -16,7 +16,7 @@ func MainTest() { flag.Parse() n := *nFlag - l := NewList[int]() + l := NewVector[int]() for i := 0; i < n; i++ { l = l.Append(i) } diff --git a/tests/benchmarks/list-prepend/main.go b/tests/benchmarks/vector-prepend/main.go index f67563d..f67563d 120000 --- a/tests/benchmarks/list-prepend/main.go +++ b/tests/benchmarks/vector-prepend/main.go diff --git a/tests/benchmarks/list-prepend/pds.go b/tests/benchmarks/vector-prepend/pds.go index 918ff72..4f82cea 100644 --- a/tests/benchmarks/list-prepend/pds.go +++ b/tests/benchmarks/vector-prepend/pds.go @@ -16,7 +16,7 @@ func MainTest() { flag.Parse() n := *nFlag - l := NewList[int]() + l := NewVector[int]() for i := 0; i < n; i++ { l = l.Prepend(i) } diff --git a/tests/benchmarks/list-set/main.go b/tests/benchmarks/vector-set/main.go index f67563d..f67563d 120000 --- a/tests/benchmarks/list-set/main.go +++ b/tests/benchmarks/vector-set/main.go diff --git a/tests/benchmarks/list-set/pds.go b/tests/benchmarks/vector-set/pds.go index e2d3709..ce0ee55 100644 --- a/tests/benchmarks/list-set/pds.go +++ b/tests/benchmarks/vector-set/pds.go @@ -16,7 +16,7 @@ func MainTest() { flag.Parse() n := *nFlag - l := NewList[int]() + l := NewVector[int]() for i := 0; i < n; i++ { l = l.Append(i) } diff --git a/tests/functional/list-api/main.go b/tests/functional/vector-api/main.go index f67563d..f67563d 120000 --- a/tests/functional/list-api/main.go +++ b/tests/functional/vector-api/main.go diff --git a/tests/functional/list-api/pds.go b/tests/functional/vector-api/pds.go index c4290c8..aa37949 100644 --- a/tests/functional/list-api/pds.go +++ b/tests/functional/vector-api/pds.go @@ -7,8 +7,8 @@ import ( func MainTest() { - g.Testing("NewList() - API usage", func() { - l := NewList[string]().Append("foo").Append("bar").Append("baz") + g.Testing("NewVector() - API usage", func() { + l := NewVector[string]().Append("foo").Append("bar").Append("baz") g.TAssertEqual(l.Get(0), "foo") g.TAssertEqual(l.Get(1), "bar") g.TAssertEqual(l.Get(2), "baz") @@ -27,8 +27,8 @@ func MainTest() { g.TAssertEqual(l.Len(), 2) }) - g.Testing("NewList().Iterator() - API usage", func() { - l := NewList[string]() + g.Testing("NewVector().Iterator() - API usage", func() { + l := NewVector[string]() l = l.Append("foo") l = l.Append("bar") l = l.Append("baz") diff --git a/tests/functional/list-builder-api/main.go b/tests/functional/vector-builder-api/main.go index f67563d..f67563d 120000 --- a/tests/functional/list-builder-api/main.go +++ b/tests/functional/vector-builder-api/main.go diff --git a/tests/functional/list-builder-api/pds.go b/tests/functional/vector-builder-api/pds.go index c7b632c..6dd8c2f 100644 --- a/tests/functional/list-builder-api/pds.go +++ b/tests/functional/vector-builder-api/pds.go @@ -8,44 +8,44 @@ import ( func MainTest() { g.Testing("API usage", func() { - b1 := NewListBuilder[string]() + b1 := NewVectorBuilder[string]() b1.Append("foo") b1.Append("bar") b1.Append("baz") - l1 := b1.List() + l1 := b1.Vector() g.TAssertEqual(l1.Get(0), "foo") g.TAssertEqual(l1.Get(1), "bar") g.TAssertEqual(l1.Get(2), "baz") - b2 := NewListBuilder[string]() + b2 := NewVectorBuilder[string]() b2.Prepend("foo") b2.Prepend("bar") b2.Prepend("baz") - l2 := b2.List() + l2 := b2.Vector() g.TAssertEqual(l2.Get(0), "baz") g.TAssertEqual(l2.Get(1), "bar") g.TAssertEqual(l2.Get(2), "foo") - b3 := NewListBuilder[string]() + b3 := NewVectorBuilder[string]() b3.Append("foo") b3.Append("bar") b3.Set(1, "___") - l3 := b3.List() + l3 := b3.Vector() g.TAssertEqual(l3.Get(0), "foo") g.TAssertEqual(l3.Get(1), "___") - b4 := NewListBuilder[string]() + b4 := NewVectorBuilder[string]() b4.Append("foo") b4.Append("bar") b4.Append("baz") b4.Slice(1, 3) - l4 := b4.List() + l4 := b4.Vector() g.TAssertEqual(l4.Len(), 2) g.TAssertEqual(l4.Get(0), "bar") g.TAssertEqual(l4.Get(1), "baz") diff --git a/tests/pds.go b/tests/pds.go index 049edae..33ef400 100644 --- a/tests/pds.go +++ b/tests/pds.go @@ -15,50 +15,50 @@ import ( -func test_NewList() { - g.TestStart("NewList[]()") +func test_NewVector() { + g.TestStart("NewVector[]()") - g.Testing("a brand new list starts empty", func() { - g.TAssertEqual(NewList[int]().Len(), 0) + g.Testing("a brand new vector starts empty", func() { + g.TAssertEqual(NewVector[int]().Len(), 0) }) } -func TestList(t *testing.T) { +func TestVector(t *testing.T) { t.Run("Shallow", func(t *testing.T) { - list := NewList[string]() - list = list.Append("foo") - if v := list.Get(0); v != "foo" { + vector := NewVector[string]() + vector = vector.Append("foo") + if v := vector.Get(0); v != "foo" { t.Fatalf("unexpected value: %v", v) } - other := list.Append("bar") + other := vector.Append("bar") if v := other.Get(0); v != "foo" { t.Fatalf("unexpected value: %v", v) } else if v := other.Get(1); v != "bar" { t.Fatalf("unexpected value: %v", v) } - if v := list.Len(); v != 1 { + if v := vector.Len(); v != 1 { t.Fatalf("unexpected value: %v", v) } }) t.Run("Deep", func(t *testing.T) { - list := NewList[int]() + vector := NewVector[int]() var array []int const n = 1000 // FIXME: 100000 was too slow for i := 0; i < n; i++ { - list = list.Append(i) + vector = vector.Append(i) array = append(array, i) } - if got, exp := len(array), list.Len(); got != exp { - t.Fatalf("List.Len()=%d, exp %d", got, exp) + if got, exp := len(array), vector.Len(); got != exp { + t.Fatalf("Vector.Len()=%d, exp %d", got, exp) } for j := range array { - if got, exp := list.Get(j), array[j]; got != exp { + if got, exp := vector.Get(j), array[j]; got != exp { t.Fatalf( - "%d. List.Get(%d)=%d, exp %d", + "%d. Vector.Get(%d)=%d, exp %d", len(array), j, got, @@ -69,18 +69,18 @@ func TestList(t *testing.T) { }) t.Run("Set", func(t *testing.T) { - list := NewList[string]() - list = list.Append("foo") - list = list.Append("bar") + vector := NewVector[string]() + vector = vector.Append("foo") + vector = vector.Append("bar") - if v := list.Get(0); v != "foo" { + if v := vector.Get(0); v != "foo" { t.Fatalf("unexpected value: %v", v) } - list = list.Set(0, "baz") - if v := list.Get(0); v != "baz" { + vector = vector.Set(0, "baz") + if v := vector.Get(0); v != "baz" { t.Fatalf("unexpected value: %v", v) - } else if v := list.Get(1); v != "bar" { + } else if v := vector.Get(1); v != "bar" { t.Fatalf("unexpected value: %v", v) } }) @@ -89,11 +89,11 @@ func TestList(t *testing.T) { var r string func() { defer func() { r = recover().(string) }() - l := NewList[string]() + l := NewVector[string]() l = l.Append("foo") l.Get(-1) }() - if r != `immutable.List.Get: index -1 out of bounds` { + if r != `immutable.Vector.Get: index -1 out of bounds` { t.Fatalf("unexpected panic: %q", r) } }) @@ -102,11 +102,11 @@ func TestList(t *testing.T) { var r string func() { defer func() { r = recover().(string) }() - l := NewList[string]() + l := NewVector[string]() l = l.Append("foo") l.Get(1) }() - if r != `immutable.List.Get: index 1 out of bounds` { + if r != `immutable.Vector.Get: index 1 out of bounds` { t.Fatalf("unexpected panic: %q", r) } }) @@ -115,11 +115,11 @@ func TestList(t *testing.T) { var r string func() { defer func() { r = recover().(string) }() - l := NewList[string]() + l := NewVector[string]() l = l.Append("foo") l.Set(1, "bar") }() - if r != `immutable.List.Set: index 1 out of bounds` { + if r != `immutable.Vector.Set: index 1 out of bounds` { t.Fatalf("unexpected panic: %q", r) } }) @@ -128,11 +128,11 @@ func TestList(t *testing.T) { var r string func() { defer func() { r = recover().(string) }() - l := NewList[string]() + l := NewVector[string]() l = l.Append("foo") l.Slice(2, 3) }() - if r != `immutable.List.Slice: start index 2 out of bounds` { + if r != `immutable.Vector.Slice: start index 2 out of bounds` { t.Fatalf("unexpected panic: %q", r) } }) @@ -141,11 +141,11 @@ func TestList(t *testing.T) { var r string func() { defer func() { r = recover().(string) }() - l := NewList[string]() + l := NewVector[string]() l = l.Append("foo") l.Slice(1, 3) }() - if r != `immutable.List.Slice: end index 3 out of bounds` { + if r != `immutable.Vector.Slice: end index 3 out of bounds` { t.Fatalf("unexpected panic: %q", r) } }) @@ -154,25 +154,25 @@ func TestList(t *testing.T) { var r string func() { defer func() { r = recover().(string) }() - l := NewList[string]() + l := NewVector[string]() l = l.Append("foo") l = l.Append("bar") l.Slice(2, 1) }() - if r != `immutable.List.Slice: invalid slice index: [2:1]` { + if r != `immutable.Vector.Slice: invalid slice index: [2:1]` { t.Fatalf("unexpected panic: %q", r) } }) t.Run("SliceBeginning", func(t *testing.T) { - l := NewList[string]() + l := NewVector[string]() l = l.Append("foo") l = l.Append("bar") l = l.Slice(1, 2) if got, exp := l.Len(), 1; got != exp { - t.Fatalf("List.Len()=%d, exp %d", got, exp) + t.Fatalf("Vector.Len()=%d, exp %d", got, exp) } else if got, exp := l.Get(0), "bar"; got != exp { - t.Fatalf("List.Get(0)=%v, exp %v", got, exp) + t.Fatalf("Vector.Get(0)=%v, exp %v", got, exp) } }) @@ -180,35 +180,35 @@ func TestList(t *testing.T) { var r string func() { defer func() { r = recover().(string) }() - l := NewList[string]() + l := NewVector[string]() l = l.Append("foo") l.Iterator().Seek(-1) }() - if r != `immutable.ListIterator.Seek: index -1 out of bounds` { + if r != `immutable.VectorIterator.Seek: index -1 out of bounds` { t.Fatalf("unexpected panic: %q", r) } }) t.Run("TestSliceFreesReferences", func(t *testing.T) { - // Test that the leaf node in a sliced list contains zero'ed + // Test that the leaf node in a sliced vector contains zero'ed // entries at the correct positions. To do this we directly - // access the internal tree structure of the list. - l := NewList[*int]() + // access the internal tree structure of the vector. + l := NewVector[*int]() var ints [5]int for i := 0; i < 5; i++ { l = l.Append(&ints[i]) } sl := l.Slice(2, 4) - var findLeaf func(listNode[*int]) *listLeafNode[*int] - findLeaf = func(n listNode[*int]) *listLeafNode[*int] { + var findLeaf func(vectorNode[*int]) *vectorLeafNode[*int] + findLeaf = func(n vectorNode[*int]) *vectorLeafNode[*int] { switch n := n.(type) { - case *listBranchNode[*int]: + case *vectorBranchNode[*int]: if n.children[0] == nil { t.Fatal("Failed to find leaf node due to nil child") } return findLeaf(n.children[0]) - case *listLeafNode[*int]: + case *vectorLeafNode[*int]: return n default: panic("Unexpected case") @@ -220,7 +220,7 @@ func TestList(t *testing.T) { t.Errorf("Expected occupied to be 1100, was %032b", leaf.occupied) } - for i := 0; i < listNodeSize; i++ { + for i := 0; i < vectorNodeSize; i++ { if 2 <= i && i < 4 { if leaf.children[i] != &ints[i] { t.Errorf("Position %v does not contain the right pointer?", i) @@ -232,12 +232,12 @@ func TestList(t *testing.T) { }) t.Run("AppendImmutable", func(t *testing.T) { - outer_l := NewList[int]() + outer_l := NewVector[int]() for N := 0; N < 1_000; N++ { l1 := outer_l.Append(0) outer_l.Append(1) if actual := l1.Get(N); actual != 0 { - t.Fatalf("Append mutates list with %d elements. Got %d instead of 0", N, actual) + t.Fatalf("Append mutates vector with %d elements. Got %d instead of 0", N, actual) } outer_l = outer_l.Append(0) @@ -246,7 +246,7 @@ func TestList(t *testing.T) { RunRandom(t, "Random", func(t *testing.T, rand *rand.Rand) { const n = 100 // FIXME: 100000 was too slow - l := newTList() + l := newTVector() for i := 0; i < n; i++ { rnd := rand.Intn(70) switch { @@ -269,29 +269,29 @@ func TestList(t *testing.T) { }) } -// TList represents a list that operates on a standard Go slice & immutable -// list. -type tList struct { - im, prev *List[int] - builder *ListBuilder[int] +// TVector represents a vector that operates on a standard Go slice & immutable +// vector. +type tVector struct { + im, prev *Vector[int] + builder *VectorBuilder[int] std []int } -// newTList returns a new instance of tList. -func newTList() *tList { - return &tList{ - im: NewList[int](), - builder: NewListBuilder[int](), +// newTVector returns a new instance of tVector. +func newTVector() *tVector { + return &tVector{ + im: NewVector[int](), + builder: NewVectorBuilder[int](), } } -// Len returns the size of the list. -func (l *tList) Len() int { +// Len returns the size of the vector. +func (l *tVector) Len() int { return len(l.std) } // ChooseIndex returns a randomly chosen, valid index from the standard slice. -func (l *tList) ChooseIndex(rand *rand.Rand) int { +func (l *tVector) ChooseIndex(rand *rand.Rand) int { if len(l.std) == 0 { return -1 } @@ -299,7 +299,7 @@ func (l *tList) ChooseIndex(rand *rand.Rand) int { } // ChooseSliceIndices returns randomly chosen, valid indices for slicing. -func (l *tList) ChooseSliceIndices(rand *rand.Rand) (start, end int) { +func (l *tVector) ChooseSliceIndices(rand *rand.Rand) (start, end int) { if len(l.std) == 0 { return 0, 0 } @@ -308,40 +308,40 @@ func (l *tList) ChooseSliceIndices(rand *rand.Rand) (start, end int) { return start, end } -// Append adds v to the end of slice and List. -func (l *tList) Append(v int) { +// Append adds v to the end of slice and Vector. +func (l *tVector) Append(v int) { l.prev = l.im l.im = l.im.Append(v) l.builder.Append(v) l.std = append(l.std, v) } -// Prepend adds v to the beginning of the slice and List. -func (l *tList) Prepend(v int) { +// Prepend adds v to the beginning of the slice and Vector. +func (l *tVector) Prepend(v int) { l.prev = l.im l.im = l.im.Prepend(v) l.builder.Prepend(v) l.std = append([]int{v}, l.std...) } -// Set updates the value at index i to v in the slice and List. -func (l *tList) Set(i, v int) { +// Set updates the value at index i to v in the slice and Vector. +func (l *tVector) Set(i, v int) { l.prev = l.im l.im = l.im.Set(i, v) l.builder.Set(i, v) l.std[i] = v } -// Slice contracts the slice and List to the range of start/end indices. -func (l *tList) Slice(start, end int) { +// Slice contracts the slice and Vector to the range of start/end indices. +func (l *tVector) Slice(start, end int) { l.prev = l.im l.im = l.im.Slice(start, end) l.builder.Slice(start, end) l.std = l.std[start:end] } -// Validate returns an error if the slice and List are different. -func (l *tList) Validate() error { +// Validate returns an error if the slice and Vector are different. +func (l *tVector) Validate() error { if got, exp := l.im.Len(), len(l.std); got != exp { return fmt.Errorf("Len()=%v, expected %d", got, exp) } else if got, exp := l.builder.Len(), len(l.std); got != exp { @@ -352,7 +352,7 @@ func (l *tList) Validate() error { if got, exp := l.im.Get(i), l.std[i]; got != exp { return fmt.Errorf("Get(%d)=%v, expected %v", i, got, exp) } else if got, exp := l.builder.Get(i), l.std[i]; got != exp { - return fmt.Errorf("Builder.List/Get(%d)=%v, expected %v", i, got, exp) + return fmt.Errorf("Builder.Vector/Get(%d)=%v, expected %v", i, got, exp) } } @@ -370,37 +370,37 @@ func (l *tList) Validate() error { return nil } -func (l *tList) validateForwardIterator(typ string, itr *ListIterator[int]) error { +func (l *tVector) validateForwardIterator(typ string, itr *VectorIterator[int]) error { for i := range l.std { if j, v := itr.Next(); i != j || l.std[i] != v { - return fmt.Errorf("ListIterator.Next()=<%v,%v>, expected <%v,%v> [%s]", j, v, i, l.std[i], typ) + return fmt.Errorf("VectorIterator.Next()=<%v,%v>, expected <%v,%v> [%s]", j, v, i, l.std[i], typ) } done := i == len(l.std)-1 if v := itr.Done(); v != done { - return fmt.Errorf("ListIterator.Done()=%v, expected %v [%s]", v, done, typ) + return fmt.Errorf("VectorIterator.Done()=%v, expected %v [%s]", v, done, typ) } } if i, v := itr.Next(); i != -1 || v != 0 { - return fmt.Errorf("ListIterator.Next()=<%v,%v>, expected DONE [%s]", i, v, typ) + return fmt.Errorf("VectorIterator.Next()=<%v,%v>, expected DONE [%s]", i, v, typ) } return nil } -func (l *tList) validateBackwardIterator(typ string, itr *ListIterator[int]) error { +func (l *tVector) validateBackwardIterator(typ string, itr *VectorIterator[int]) error { itr.Last() for i := len(l.std) - 1; i >= 0; i-- { if j, v := itr.Prev(); i != j || l.std[i] != v { - return fmt.Errorf("ListIterator.Prev()=<%v,%v>, expected <%v,%v> [%s]", j, v, i, l.std[i], typ) + return fmt.Errorf("VectorIterator.Prev()=<%v,%v>, expected <%v,%v> [%s]", j, v, i, l.std[i], typ) } done := i == 0 if v := itr.Done(); v != done { - return fmt.Errorf("ListIterator.Done()=%v, expected %v [%s]", v, done, typ) + return fmt.Errorf("VectorIterator.Done()=%v, expected %v [%s]", v, done, typ) } } if i, v := itr.Prev(); i != -1 || v != 0 { - return fmt.Errorf("ListIterator.Prev()=<%v,%v>, expected DONE [%s]", i, v, typ) + return fmt.Errorf("VectorIterator.Prev()=<%v,%v>, expected DONE [%s]", i, v, typ) } return nil } @@ -2030,10 +2030,10 @@ func TestSortedSetBuilder(t *testing.T) { func MainTest() { - test_NewList() + test_NewVector() tests := []testing.InternalTest{ - { "TestList", TestList }, + { "TestVector", TestVector }, { "TestInternal_mapNode_Overwrite", TestInternal_mapNode_Overwrite }, { "TestInternal_mapArrayNode", TestInternal_mapArrayNode }, { "TestInternal_mapValueNode", TestInternal_mapValueNode }, |