11package iter
22
3- import "github.com/BooleanCat/go-functional/option"
3+ import (
4+ "sync"
5+
6+ "github.com/BooleanCat/go-functional/option"
7+ )
48
59// LiftIter implements `Lift`. See `Lift`'s documentation.
610type LiftIter [T any ] struct {
@@ -26,3 +30,64 @@ func (iter *LiftIter[T]) Next() option.Option[T] {
2630}
2731
2832var _ Iterator [struct {}] = new (LiftIter [struct {}])
33+
34+ // LiftHashMapIter implements `LiftHashMap`. See `LiftHashMap`'s documentation.
35+ type LiftHashMapIter [T comparable , U any ] struct {
36+ hashmap map [T ]U
37+ items chan Tuple [T , U ]
38+ stopOnce sync.Once
39+ stop chan struct {}
40+ }
41+
42+ // LiftHashMap instantiates a `LiftHashMapIter` that will yield all items in
43+ // the provided map in the form iter.Tuple[key, value].
44+ //
45+ // Unlike most iterators, `LiftHashMap` should be closed after usage (because).
46+ // The iterator is closed when any of the two conditions are met.
47+ //
48+ // 1. The caller explicitly invokes the `Close` method.
49+ // 2. The iterator is exhausted.
50+ //
51+ // It is safe to call Close multiple times or after exhaustion. It is not
52+ // necessary to call Close if exhaustion is guaranteed, but may be wise to
53+ // redundantly call Close if you're unsure.
54+ func LiftHashMap [T comparable , U any ](hashmap map [T ]U ) * LiftHashMapIter [T , U ] {
55+ iter := & LiftHashMapIter [T , U ]{hashmap , make (chan Tuple [T , U ]), sync.Once {}, make (chan struct {})}
56+
57+ go func () {
58+ defer close (iter .items )
59+ defer iter .stopOnce .Do (func () { close (iter .stop ) })
60+ outer:
61+ for k , v := range hashmap {
62+ select {
63+ case iter .items <- Tuple [T , U ]{k , v }:
64+ continue
65+ case <- iter .stop :
66+ break outer
67+ }
68+
69+ }
70+ }()
71+
72+ return iter
73+ }
74+
75+ // Close the iterator. See `LiftHashMap` documentation for details.
76+ func (iter * LiftHashMapIter [T , U ]) Close () {
77+ iter .stopOnce .Do (func () {
78+ iter .stop <- struct {}{}
79+ close (iter .stop )
80+ })
81+ }
82+
83+ // Next implements the Iterator interface for `LiftHashMap`.
84+ func (iter * LiftHashMapIter [T , U ]) Next () option.Option [Tuple [T , U ]] {
85+ pair , ok := <- iter .items
86+ if ! ok {
87+ return option .None [Tuple [T , U ]]()
88+ }
89+
90+ return option .Some (pair )
91+ }
92+
93+ var _ Iterator [Tuple [struct {}, struct {}]] = new (LiftHashMapIter [struct {}, struct {}])
0 commit comments