From 9c9992065bb51782b885afe22e2b3f0e9804b280 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 17 Jul 2023 10:27:51 +0200 Subject: [PATCH] add simple generic Iterator definition and implementation --- lib/funky/funky.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ tests/funky_test.go | 9 +++++++++ 2 files changed, 54 insertions(+) diff --git a/lib/funky/funky.go b/lib/funky/funky.go index 98394e6..5a8e946 100644 --- a/lib/funky/funky.go +++ b/lib/funky/funky.go @@ -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 +} diff --git a/tests/funky_test.go b/tests/funky_test.go index 2e24c88..e1afb16 100644 --- a/tests/funky_test.go +++ b/tests/funky_test.go @@ -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) +}