// 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 } type maybe[V any] struct { isNothing bool value V } func Nothing[V any]() Maybe[V] { return &maybe[V]{isNothing: true} } func Just[V any](v V) Maybe[V] { return &maybe[V]{false, v} } func (m *maybe[V]) IsNothing() bool { return m.isNothing } 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 }