Skip to content

Commit 5c0ab2b

Browse files
authored
Added iterators to sync2 package (#43)
* Added iterators to sync2 package * Added missing license * Fix version incompatibility
1 parent 6acb6c8 commit 5c0ab2b

File tree

11 files changed

+423
-0
lines changed

11 files changed

+423
-0
lines changed

go.work

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// SPDX-FileCopyrightText: 2025 Kalle Fagerberg
2+
//
3+
// SPDX-License-Identifier: CC0-1.0
4+
5+
go 1.23
6+
7+
use (
8+
.
9+
./sync2/internal/go_1_23
10+
)

go.work.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
gopkg.in/typ.v4 v4.3.1/go.mod h1:wolXe8DlewxRCjA7SOiT3zjrZ0eQJZcr8cmV6bQWJUM=

go.work.sum.license

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SPDX-FileCopyrightText: 2025 Kalle Fagerberg
2+
3+
SPDX-License-Identifier: CC0-1.0

sync2/internal/go_1_23/go.mod

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// SPDX-FileCopyrightText: 2025 Kalle Fagerberg
2+
//
3+
// SPDX-License-Identifier: CC0-1.0
4+
5+
module gopkg.in/typ.v4/internal/go_1_23
6+
7+
go 1.23
8+
9+
require gopkg.in/typ.v4 v4.3.1

sync2/internal/go_1_23/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
gopkg.in/typ.v4 v4.3.1 h1:z3vGwIIn2X8GjP589+YS8YWmpNqBFEy0w7OcGWj0NZ4=
2+
gopkg.in/typ.v4 v4.3.1/go.mod h1:wolXe8DlewxRCjA7SOiT3zjrZ0eQJZcr8cmV6bQWJUM=

sync2/internal/go_1_23/go.sum.license

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SPDX-FileCopyrightText: 2025 Kalle Fagerberg
2+
3+
SPDX-License-Identifier: CC0-1.0
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// SPDX-FileCopyrightText: 2025 Kalle Fagerberg
2+
//
3+
// SPDX-License-Identifier: MIT
4+
5+
package go123_test
6+
7+
import (
8+
"maps"
9+
"testing"
10+
11+
"gopkg.in/typ.v4/sync2"
12+
)
13+
14+
func TestMapIterCompiles(t *testing.T) {
15+
m := new(sync2.Map[int, string])
16+
17+
for range sync2.MapAll(m) {
18+
// do nothing
19+
}
20+
for range sync2.MapKeys(m) {
21+
// do nothing
22+
}
23+
for range sync2.MapValues(m) {
24+
// do nothing
25+
}
26+
27+
otherMap := map[int]string{}
28+
sync2.MapInsert(m, maps.All(otherMap))
29+
_ = sync2.MapCollect(maps.All(otherMap))
30+
}

sync2/map_example_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// SPDX-FileCopyrightText: 2025 Kalle Fagerberg
2+
//
3+
// SPDX-License-Identifier: MIT
4+
5+
package sync2_test
6+
7+
import (
8+
"fmt"
9+
10+
"gopkg.in/typ.v4/sync2"
11+
)
12+
13+
func ExampleMap() {
14+
m := new(sync2.Map[int, string])
15+
m.Store(1, "one")
16+
m.Store(2, "two")
17+
m.Store(3, "three")
18+
19+
fmt.Println("Len:", m.Len())
20+
21+
// Output:
22+
// Len: 3
23+
}
24+
25+
func ExampleMap_Load() {
26+
m := new(sync2.Map[int, string])
27+
m.Store(1, "one")
28+
m.Store(2, "two")
29+
m.Store(3, "three")
30+
31+
if value, ok := m.Load(0); ok {
32+
fmt.Println("Map[0]:", value)
33+
} else {
34+
fmt.Println("Map[0]: (no value)")
35+
}
36+
37+
if value, ok := m.Load(1); ok {
38+
fmt.Println("Map[1]:", value)
39+
} else {
40+
fmt.Println("Map[1]: (no value)")
41+
}
42+
43+
// Output:
44+
// Map[0]: (no value)
45+
// Map[1]: one
46+
}

sync2/map_iter.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// SPDX-FileCopyrightText: 2025 Kalle Fagerberg
2+
//
3+
// SPDX-License-Identifier: MIT
4+
5+
package sync2
6+
7+
// MapAll returns an iterator over key-value pairs in m.
8+
// The iteeration order is not specified and is not guaranteed to be the same
9+
// from one call to the next.
10+
func MapAll[K comparable, V any](m *Map[K, V]) func(yield func(K, V) bool) {
11+
return func(yield func(K, V) bool) {
12+
m.Range(func(key K, value V) bool {
13+
return yield(key, value)
14+
})
15+
}
16+
}
17+
18+
// MapKeys returns an iterator over keys in m.
19+
// The iteeration order is not specified and is not guaranteed to be the same
20+
// from one call to the next.
21+
func MapKeys[K comparable, V any](m *Map[K, V]) func(yield func(K) bool) {
22+
return func(yield func(K) bool) {
23+
m.Range(func(key K, _ V) bool {
24+
return yield(key)
25+
})
26+
}
27+
}
28+
29+
// MapValues returns an iterator over values in m.
30+
// The iteeration order is not specified and is not guaranteed to be the same
31+
// from one call to the next.
32+
func MapValues[K comparable, V any](m *Map[K, V]) func(yield func(V) bool) {
33+
return func(yield func(V) bool) {
34+
m.Range(func(_ K, value V) bool {
35+
return yield(value)
36+
})
37+
}
38+
}
39+
40+
// MapInsert adds the key-value pairs from seq to m.
41+
// If a key in seq already exists in m, its value will be overwritten.
42+
func MapInsert[K comparable, V any](m *Map[K, V], iter func(yield func(K, V) bool)) {
43+
iter(func(k K, v V) bool {
44+
m.Store(k, v)
45+
return true
46+
})
47+
}
48+
49+
// MapCollect collects key-value pairs from seq into a new map
50+
// and returns it.
51+
func MapCollect[K comparable, V any](iter func(yield func(K, V) bool)) *Map[K, V] {
52+
m := new(Map[K, V])
53+
iter(func(k K, v V) bool {
54+
m.Store(k, v)
55+
return true
56+
})
57+
return m
58+
}

sync2/map_iter_example_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// SPDX-FileCopyrightText: 2025 Kalle Fagerberg
2+
//
3+
// SPDX-License-Identifier: MIT
4+
5+
package sync2_test
6+
7+
import (
8+
"gopkg.in/typ.v4/sync2"
9+
)
10+
11+
func ExampleMapAll() {
12+
m := new(sync2.Map[int, string])
13+
m.Store(1, "one")
14+
m.Store(2, "two")
15+
16+
// In Go 1.23+ you can iterate the values like so:
17+
/*
18+
for k, v := range sync2.MapAll(m) {
19+
fmt.Printf("%s: %q\n", k, v)
20+
}
21+
*/
22+
}
23+
24+
func ExampleMapKeys() {
25+
m := new(sync2.Map[int, string])
26+
m.Store(1, "one")
27+
m.Store(2, "two")
28+
29+
// In Go 1.23+ you can iterate the values like so:
30+
/*
31+
for k := range sync2.MapKeys(m) {
32+
fmt.Printf("key: %s\n", k)
33+
}
34+
*/
35+
}
36+
37+
func ExampleMapValues() {
38+
m := new(sync2.Map[int, string])
39+
m.Store(1, "one")
40+
m.Store(2, "two")
41+
42+
// In Go 1.23+ you can iterate the values like so:
43+
/*
44+
for k := range sync2.MapValues(m) {
45+
fmt.Printf("value: %q\n", v)
46+
}
47+
*/
48+
49+
// Alternatively you can get a slice of keys like so:
50+
/*
51+
keys := slices.Collect(sync2.MapValues(m))
52+
*/
53+
}

0 commit comments

Comments
 (0)