add simple generic Iterator definition and implementation

This commit is contained in:
Helmut Merz 2023-07-17 10:27:51 +02:00
parent d3c85de61f
commit 9c9992065b
2 changed files with 54 additions and 0 deletions

View file

@ -1,5 +1,9 @@
// Package funky provides a few constructs usually present in pure
// functional programming environments, using Go 1.18 generics.
package funky
// Maybe (sometimes called `Option`)
type Maybe[V any] interface {
IsNothing() bool
Value() V
@ -25,3 +29,44 @@ func (m *maybe[V]) IsNothing() bool {
func (m *maybe[V]) Value() V {
return m.value
}
// Iterator
type Iterator[V any] interface {
Maybe[V]
Next() Maybe[V]
}
type sliceIt[V any] struct {
idx int
slice []V
}
func SliceIterator[V any](sl []V) Iterator[V] {
return &sliceIt[V]{slice: sl}
}
func (it *sliceIt[V]) Next() Maybe[V] {
if it.IsNothing() {
return Nothing[V]()
}
v := it.Value()
it.idx++
return Just(v)
}
func (it *sliceIt[V]) IsNothing() bool {
return it.idx >= len(it.slice)
}
func (it *sliceIt[V]) Value() V {
return it.slice[it.idx]
}
func Slice[V any](it Iterator[V]) []V {
var out []V
for m := it.Next(); !m.IsNothing(); m = it.Next() {
out = append(out, m.Value())
}
return out
}

View file

@ -10,6 +10,7 @@ import (
func TestFunky(tb *tbase.T) {
t := testing.SetUp(tb)
t.Run("maybe", MaybeTest)
t.Run("iterator", IteratorTest)
}
func MaybeTest(t *testing.T) {
@ -19,3 +20,11 @@ func MaybeTest(t *testing.T) {
t.AssertEqual(i1.IsNothing(), false)
t.AssertEqual(i1.Value(), 3)
}
func IteratorTest(t *testing.T) {
sl := []int{3, 4, 5}
var it funky.Iterator[int] = funky.SliceIterator[int](sl)
s12 := funky.Slice(it)
t.AssertEqual(len(s12), 3)
t.AssertEqual(s12[1], 4)
}