From addaee3a476e3af23b897a3b75ebbd089b995e7c Mon Sep 17 00:00:00 2001 From: jpfourny Date: Wed, 10 Jan 2024 22:21:18 -0500 Subject: [PATCH] Adding optional.Map and optional.Optional.OrElseZero --- pkg/optional/optional.go | 33 +++++++++++++++++++++++++++++++ pkg/optional/optional_test.go | 37 +++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/pkg/optional/optional.go b/pkg/optional/optional.go index ea91f88..98349f6 100644 --- a/pkg/optional/optional.go +++ b/pkg/optional/optional.go @@ -24,6 +24,9 @@ type Optional[V any] interface { // OrElse returns the value contained in the Optional if the Optional is not empty, or the provided value otherwise. OrElse(V) V + // OrElseZero returns the value contained in the Optional if the Optional is not empty, or the zero value of type V otherwise. + OrElseZero() V + // OrElseGet returns the value contained in the Optional if the Optional is not empty, or the result of the provided function otherwise. OrElseGet(func() V) V } @@ -54,6 +57,11 @@ func (n None[V]) OrElse(v V) V { return v } +func (n None[V]) OrElseZero() V { + var zero V + return zero +} + func (n None[V]) OrElseGet(f func() V) V { return f() } @@ -85,6 +93,10 @@ func (s Some[V]) OrElse(V) V { return s.Value } +func (s Some[V]) OrElseZero() V { + return s.Value +} + func (s Some[V]) OrElseGet(_ func() V) V { return s.Value } @@ -114,3 +126,24 @@ func Maybe[V any](value V, ok bool) Optional[V] { func Empty[V any]() Optional[V] { return None[V]{} } + +// Map returns an Optional containing the result of applying the provided function to the value contained in the provided Optional. +// If the provided Optional is empty, an empty Optional is returned. +// +// Example usage: +// +// o := optional.Map( +// optional.Of(1), +// func(i int) string { return fmt.Sprintf("%d", i) }, +// ) // optional.Some("1") +// +// o = optional.Map( +// optional.Empty[int](), +// func(i int) string { return fmt.Sprintf("%d", i) }, +// ) // optional.None() +func Map[V, U any](o Optional[V], mapper func(V) U) Optional[U] { + if o.Present() { + return Of(mapper(o.Get())) + } + return Empty[U]() +} diff --git a/pkg/optional/optional_test.go b/pkg/optional/optional_test.go index 468a9c5..d110bd5 100644 --- a/pkg/optional/optional_test.go +++ b/pkg/optional/optional_test.go @@ -46,6 +46,27 @@ func TestEmpty(t *testing.T) { } } +func TestMap(t *testing.T) { + t.Run("Some", func(t *testing.T) { + o := Of(42) + m := Map(o, func(i int) string { return "foo" }) + if !m.Present() { + t.Errorf("expected Present() to be true") + } + if m.Get() != "foo" { + t.Errorf("expected Get() to return %q", "foo") + } + }) + + t.Run("None", func(t *testing.T) { + o := Empty[int]() + m := Map(o, func(i int) string { return "foo" }) + if m.Present() { + t.Errorf("expected Present() to be false") + } + }) +} + func TestIfPresent(t *testing.T) { t.Run("Some", func(t *testing.T) { var called bool @@ -120,6 +141,22 @@ func TestOrElse(t *testing.T) { }) } +func TestOrElseZero(t *testing.T) { + t.Run("Some", func(t *testing.T) { + o := Of(42) + if o.OrElseZero() != 42 { + t.Errorf("expected OrElseZero to return 42") + } + }) + + t.Run("None", func(t *testing.T) { + o := Empty[int]() + if o.OrElseZero() != 0 { + t.Errorf("expected OrElseZero to return 0") + } + }) +} + func TestOrElseGet(t *testing.T) { t.Run("Some", func(t *testing.T) { o := Of(42)