Skip to content

Commit 4dd1fd8

Browse files
authored
Merge pull request #35 from laher/sets-maps-append-multi
Sets & maps append-multi. Also docs and a fix for SortedSets
2 parents 92be7cb + 90fd331 commit 4dd1fd8

File tree

5 files changed

+212
-21
lines changed

5 files changed

+212
-21
lines changed

README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Immutable ![release](https://img.shields.io/github/release/benbjohnson/immutable
22
=========
33

44
This repository contains *generic* immutable collection types for Go. It includes
5-
`List`, `Map`, and `SortedMap` implementations. Immutable collections can
5+
`List`, `Map`, `SortedMap`, `Set` and `SortedSet` implementations. Immutable collections can
66
provide efficient, lock free sharing of data by requiring that edits to the
77
collections return new collections.
88

@@ -284,6 +284,29 @@ type Comparer[K comparable] interface {
284284

285285
Please see the internal `defaultComparer` for an example, bearing in mind that it works for several types.
286286

287+
## Set
288+
289+
The `Set` represents a collection of unique values. It uses a `map[T]struct{}`, so it carries over some characteristics from the built-in Go `map` type.
290+
Values neeed to be `comparable`.
291+
292+
Like Maps, Sets require a `Hasher` to hash keys and check for equality. There are built-in
293+
hasher implementations for most primitive types such as `int`, `uint`, and
294+
`string` keys. You may pass in a `nil` hasher to `NewMap()` if you are using
295+
one of these key types.
296+
297+
298+
## Sorted Set
299+
300+
The `SortedSet` represents a sorted collection of unique values.
301+
Unlike the `Set`, however, keys can be iterated over in-order. It is implemented
302+
as a B+tree.
303+
304+
Sorted sets require a `Comparer` to sort values and check for equality. There are
305+
built-in comparer implementations for `int`, `uint`, and `string` keys. You may
306+
pass a `nil` comparer to `NewSortedSet()` if you are using one of these key
307+
types.
308+
309+
The API is identical to the `Set` implementation.
287310

288311

289312
## Contributing

immutable.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,20 @@ func NewMap[K comparable, V any](hasher Hasher[K]) *Map[K, V] {
707707
}
708708
}
709709

710+
// NewMapOf returns a new instance of Map, containing a map of provided entries.
711+
//
712+
// If hasher is nil, a default hasher implementation will automatically be chosen based on the first key added.
713+
// Default hasher implementations only exist for int, string, and byte slice types.
714+
func NewMapOf[K comparable, V any](hasher Hasher[K], entries map[K]V) *Map[K, V] {
715+
m := &Map[K, V]{
716+
hasher: hasher,
717+
}
718+
for k, v := range entries {
719+
m.set(k, v, true)
720+
}
721+
return m
722+
}
723+
710724
// Len returns the number of elements in the map.
711725
func (m *Map[K, V]) Len() int {
712726
return m.size
@@ -738,6 +752,18 @@ func (m *Map[K, V]) Set(key K, value V) *Map[K, V] {
738752
return m.set(key, value, false)
739753
}
740754

755+
// SetMany returns a map with the keys set to the new values. nil values are allowed.
756+
//
757+
// This function will return a new map even if the updated value is the same as
758+
// the existing value because Map does not track value equality.
759+
func (m *Map[K, V]) SetMany(entries map[K]V) *Map[K, V] {
760+
n := m.clone()
761+
for k, v := range entries {
762+
n.set(k, v, true)
763+
}
764+
return n
765+
}
766+
741767
func (m *Map[K, V]) set(key K, value V, mutable bool) *Map[K, V] {
742768
// Set a hasher on the first value if one does not already exist.
743769
hasher := m.hasher
@@ -1582,6 +1608,20 @@ func NewSortedMap[K comparable, V any](comparer Comparer[K]) *SortedMap[K, V] {
15821608
}
15831609
}
15841610

1611+
// NewSortedMapOf returns a new instance of SortedMap, containing a map of provided entries.
1612+
//
1613+
// If comparer is nil then a default comparer is set after the first key is inserted. Default comparers
1614+
// exist for int, string, and byte slice keys.
1615+
func NewSortedMapOf[K comparable, V any](comparer Comparer[K], entries map[K]V) *SortedMap[K, V] {
1616+
m := &SortedMap[K, V]{
1617+
comparer: comparer,
1618+
}
1619+
for k, v := range entries {
1620+
m.set(k, v, true)
1621+
}
1622+
return m
1623+
}
1624+
15851625
// Len returns the number of elements in the sorted map.
15861626
func (m *SortedMap[K, V]) Len() int {
15871627
return m.size
@@ -1602,6 +1642,15 @@ func (m *SortedMap[K, V]) Set(key K, value V) *SortedMap[K, V] {
16021642
return m.set(key, value, false)
16031643
}
16041644

1645+
// SetMany returns a map with the keys set to the new values.
1646+
func (m *SortedMap[K, V]) SetMany(entries map[K]V) *SortedMap[K, V] {
1647+
n := m.clone()
1648+
for k, v := range entries {
1649+
n.set(k, v, true)
1650+
}
1651+
return n
1652+
}
1653+
16051654
func (m *SortedMap[K, V]) set(key K, value V, mutable bool) *SortedMap[K, V] {
16061655
// Set a comparer on the first value if one does not already exist.
16071656
comparer := m.comparer

immutable_test.go

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,10 @@ func TestList(t *testing.T) {
200200
t.Fatal("Failed to find leaf node due to nil child")
201201
}
202202
return findLeaf(n.children[0])
203-
case *listLeafNode[*int]: return n
204-
default: panic("Unexpected case")
203+
case *listLeafNode[*int]:
204+
return n
205+
default:
206+
panic("Unexpected case")
205207
}
206208
}
207209

@@ -959,6 +961,22 @@ func TestMap_Set(t *testing.T) {
959961
}
960962
})
961963

964+
t.Run("Multi", func(t *testing.T) {
965+
m := NewMapOf(nil, map[int]string{1: "foo"})
966+
itr := m.Iterator()
967+
if itr.Done() {
968+
t.Fatal("MapIterator.Done()=false, expected true")
969+
}
970+
if k, v, ok := itr.Next(); !ok {
971+
t.Fatalf("MapIterator.Next()!=ok, expected ok")
972+
} else if k != 1 || v != "foo" {
973+
t.Fatalf("MapIterator.Next()=<%v,%v>, expected <1, \"foo\">", k, v)
974+
}
975+
if k, v, ok := itr.Next(); ok {
976+
t.Fatalf("MapIterator.Next()=<%v,%v>, expected nil", k, v)
977+
}
978+
})
979+
962980
t.Run("VerySmall", func(t *testing.T) {
963981
const n = 6
964982
m := NewMap[int, int](nil)
@@ -1070,6 +1088,16 @@ func TestMap_Overwrite(t *testing.T) {
10701088
t.Fatalf("Get(%d)=<%v,%v>", i, v, ok)
10711089
}
10721090
}
1091+
1092+
t.Run("Simple", func(t *testing.T) {
1093+
m := NewMap[int, string](nil)
1094+
itr := m.Iterator()
1095+
if !itr.Done() {
1096+
t.Fatal("MapIterator.Done()=true, expected false")
1097+
} else if k, v, ok := itr.Next(); ok {
1098+
t.Fatalf("MapIterator.Next()=<%v,%v>, expected nil", k, v)
1099+
}
1100+
})
10731101
}
10741102

10751103
func TestMap_Delete(t *testing.T) {

sets.go

Lines changed: 107 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,98 @@
11
package immutable
22

3+
// Set represents a collection of unique values. The set uses a Hasher
4+
// to generate hashes and check for equality of key values.
5+
//
6+
// Internally, the Set stores values as keys of a Map[T,struct{}]
37
type Set[T comparable] struct {
48
m *Map[T, struct{}]
59
}
610

7-
func NewSet[T comparable](hasher Hasher[T]) Set[T] {
8-
return Set[T]{
11+
// NewSet returns a new instance of Set.
12+
//
13+
// If hasher is nil, a default hasher implementation will automatically be chosen based on the first key added.
14+
// Default hasher implementations only exist for int, string, and byte slice types.
15+
// NewSet can also take some initial values as varargs.
16+
func NewSet[T comparable](hasher Hasher[T], values ...T) Set[T] {
17+
s := Set[T]{
918
m: NewMap[T, struct{}](hasher),
1019
}
20+
for _, value := range values {
21+
s.m.set(value, struct{}{}, true)
22+
}
23+
return s
1124
}
1225

13-
func (s Set[T]) Set(val T) Set[T] {
14-
return Set[T]{
15-
m: s.m.Set(val, struct{}{}),
26+
// Set returns a set containing the new value.
27+
//
28+
// This function will return a new set even if the set already contains the value.
29+
func (s Set[T]) Set(values ...T) Set[T] {
30+
n := Set[T]{
31+
m: s.m.clone(),
32+
}
33+
for _, value := range values {
34+
n.m.set(value, struct{}{}, true)
1635
}
36+
return n
1737
}
1838

19-
func (s Set[T]) Delete(val T) Set[T] {
20-
return Set[T]{
21-
m: s.m.Delete(val),
39+
// Delete returns a set with the given key removed.
40+
func (s Set[T]) Delete(values ...T) Set[T] {
41+
n := Set[T]{
42+
m: s.m.clone(),
43+
}
44+
for _, value := range values {
45+
n.m.delete(value, true)
2246
}
47+
return n
2348
}
2449

50+
// Has returns true when the set contains the given value
2551
func (s Set[T]) Has(val T) bool {
2652
_, ok := s.m.Get(val)
2753
return ok
2854
}
2955

56+
// Len returns the number of elements in the underlying map.
3057
func (s Set[K]) Len() int {
3158
return s.m.Len()
3259
}
3360

61+
// Items returns a slice of the items inside the set
62+
func (s Set[T]) Items() []T {
63+
r := make([]T, 0, s.Len())
64+
itr := s.Iterator()
65+
for !itr.Done() {
66+
v, _ := itr.Next()
67+
r = append(r, v)
68+
}
69+
return r
70+
}
71+
72+
// Iterator returns a new iterator for this set positioned at the first value.
3473
func (s Set[T]) Iterator() *SetIterator[T] {
3574
itr := &SetIterator[T]{mi: s.m.Iterator()}
3675
itr.mi.First()
3776
return itr
3877
}
3978

79+
// SetIterator represents an iterator over a set.
80+
// Iteration can occur in natural or reverse order based on use of Next() or Prev().
4081
type SetIterator[T comparable] struct {
4182
mi *MapIterator[T, struct{}]
4283
}
4384

85+
// Done returns true if no more values remain in the iterator.
4486
func (itr *SetIterator[T]) Done() bool {
4587
return itr.mi.Done()
4688
}
4789

90+
// First moves the iterator to the first value.
4891
func (itr *SetIterator[T]) First() {
4992
itr.mi.First()
5093
}
5194

95+
// Next moves the iterator to the next value.
5296
func (itr *SetIterator[T]) Next() (val T, ok bool) {
5397
val, _, ok = itr.mi.Next()
5498
return
@@ -82,65 +126,112 @@ type SortedSet[T comparable] struct {
82126
m *SortedMap[T, struct{}]
83127
}
84128

85-
func NewSortedSet[T comparable](comparer Comparer[T]) SortedSet[T] {
86-
return SortedSet[T]{
129+
// NewSortedSet returns a new instance of SortedSet.
130+
//
131+
// If comparer is nil then
132+
// a default comparer is set after the first key is inserted. Default comparers
133+
// exist for int, string, and byte slice keys.
134+
// NewSortedSet can also take some initial values as varargs.
135+
func NewSortedSet[T comparable](comparer Comparer[T], values ...T) SortedSet[T] {
136+
s := SortedSet[T]{
87137
m: NewSortedMap[T, struct{}](comparer),
88138
}
139+
for _, value := range values {
140+
s.m.set(value, struct{}{}, true)
141+
}
142+
return s
89143
}
90144

91-
func (s SortedSet[T]) Put(val T) SortedSet[T] {
92-
return SortedSet[T]{
93-
m: s.m.Set(val, struct{}{}),
145+
// Set returns a set containing the new value.
146+
//
147+
// This function will return a new set even if the set already contains the value.
148+
func (s SortedSet[T]) Set(values ...T) SortedSet[T] {
149+
n := SortedSet[T]{
150+
m: s.m.clone(),
151+
}
152+
for _, value := range values {
153+
n.m.set(value, struct{}{}, true)
94154
}
155+
return n
95156
}
96157

97-
func (s SortedSet[T]) Delete(val T) SortedSet[T] {
98-
return SortedSet[T]{
99-
m: s.m.Delete(val),
158+
// Delete returns a set with the given key removed.
159+
func (s SortedSet[T]) Delete(values ...T) SortedSet[T] {
160+
n := SortedSet[T]{
161+
m: s.m.clone(),
162+
}
163+
for _, value := range values {
164+
n.m.delete(value, true)
100165
}
166+
return n
101167
}
102168

169+
// Has returns true when the set contains the given value
103170
func (s SortedSet[T]) Has(val T) bool {
104171
_, ok := s.m.Get(val)
105172
return ok
106173
}
107174

175+
// Len returns the number of elements in the underlying map.
108176
func (s SortedSet[K]) Len() int {
109177
return s.m.Len()
110178
}
111179

180+
// Items returns a slice of the items inside the set
181+
func (s SortedSet[T]) Items() []T {
182+
r := make([]T, 0, s.Len())
183+
itr := s.Iterator()
184+
for !itr.Done() {
185+
v, _ := itr.Next()
186+
r = append(r, v)
187+
}
188+
return r
189+
}
190+
191+
// Iterator returns a new iterator for this set positioned at the first value.
112192
func (s SortedSet[T]) Iterator() *SortedSetIterator[T] {
113193
itr := &SortedSetIterator[T]{mi: s.m.Iterator()}
114194
itr.mi.First()
115195
return itr
116196
}
117197

198+
// SortedSetIterator represents an iterator over a sorted set.
199+
// Iteration can occur in natural or reverse order based on use of Next() or Prev().
118200
type SortedSetIterator[T comparable] struct {
119201
mi *SortedMapIterator[T, struct{}]
120202
}
121203

204+
// Done returns true if no more values remain in the iterator.
122205
func (itr *SortedSetIterator[T]) Done() bool {
123206
return itr.mi.Done()
124207
}
125208

209+
// First moves the iterator to the first value.
126210
func (itr *SortedSetIterator[T]) First() {
127211
itr.mi.First()
128212
}
129213

214+
// Last moves the iterator to the last value.
130215
func (itr *SortedSetIterator[T]) Last() {
131216
itr.mi.Last()
132217
}
133218

219+
// Next moves the iterator to the next value.
134220
func (itr *SortedSetIterator[T]) Next() (val T, ok bool) {
135221
val, _, ok = itr.mi.Next()
136222
return
137223
}
138224

225+
// Next moves the iterator to the previous value.
139226
func (itr *SortedSetIterator[T]) Prev() (val T, ok bool) {
140227
val, _, ok = itr.mi.Prev()
141228
return
142229
}
143230

231+
// Next moves the iterator to the given value.
232+
//
233+
// If the value does not exist then the next value is used. If no more keys exist
234+
// then the iterator is marked as done.
144235
func (itr *SortedSetIterator[T]) Seek(val T) {
145236
itr.mi.Seek(val)
146237
}

0 commit comments

Comments
 (0)