add simple generic Iterator definition and implementation
This commit is contained in:
parent
d3c85de61f
commit
9c9992065b
2 changed files with 54 additions and 0 deletions
|
@ -1,5 +1,9 @@
|
||||||
|
// Package funky provides a few constructs usually present in pure
|
||||||
|
// functional programming environments, using Go 1.18 generics.
|
||||||
package funky
|
package funky
|
||||||
|
|
||||||
|
// Maybe (sometimes called `Option`)
|
||||||
|
|
||||||
type Maybe[V any] interface {
|
type Maybe[V any] interface {
|
||||||
IsNothing() bool
|
IsNothing() bool
|
||||||
Value() V
|
Value() V
|
||||||
|
@ -25,3 +29,44 @@ func (m *maybe[V]) IsNothing() bool {
|
||||||
func (m *maybe[V]) Value() V {
|
func (m *maybe[V]) Value() V {
|
||||||
return m.value
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
func TestFunky(tb *tbase.T) {
|
func TestFunky(tb *tbase.T) {
|
||||||
t := testing.SetUp(tb)
|
t := testing.SetUp(tb)
|
||||||
t.Run("maybe", MaybeTest)
|
t.Run("maybe", MaybeTest)
|
||||||
|
t.Run("iterator", IteratorTest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MaybeTest(t *testing.T) {
|
func MaybeTest(t *testing.T) {
|
||||||
|
@ -19,3 +20,11 @@ func MaybeTest(t *testing.T) {
|
||||||
t.AssertEqual(i1.IsNothing(), false)
|
t.AssertEqual(i1.IsNothing(), false)
|
||||||
t.AssertEqual(i1.Value(), 3)
|
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)
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue