diff options
| -rw-r--r-- | CHANGELOG.md | 6 | ||||
| -rw-r--r-- | options/options.go | 48 | ||||
| -rw-r--r-- | options/options_test.go | 40 |
3 files changed, 93 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index a201d67..da568b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v1.1.0 (TBD) + +Changes: + +- Add `options.Max()` and `options.Min()`. + # v1.0.0 (2025-02-12) Initial release. The Go version requirement is 1.24.0 because `type Option` diff --git a/options/options.go b/options/options.go index bfae710..110b212 100644 --- a/options/options.go +++ b/options/options.go @@ -8,7 +8,11 @@ // that cannot be expressed as methods on the Option type itself. package options -import . "github.com/majewsky/gg/option" +import ( + "cmp" + + . "github.com/majewsky/gg/option" +) // NOTE: Keep functions sorted by name. @@ -37,3 +41,45 @@ func Map[T, U any](o Option[T], mapping func(T) U) Option[U] { return None[U]() } } + +// Max returns the largest of its input values, while disregarding None values. +// If there are no Some values, None is returned. +func Max[T cmp.Ordered](inputs ...Option[T]) Option[T] { + var ( + result T + isSome = false + ) + for _, i := range inputs { + value, ok := i.Unpack() + if ok && (!isSome || result < value) { + result = value + isSome = true + } + } + if isSome { + return Some(result) + } else { + return None[T]() + } +} + +// Min returns the smallest of its input values, while disregarding None values. +// If there are no Some values, None is returned. +func Min[T cmp.Ordered](inputs ...Option[T]) Option[T] { + var ( + result T + isSome = false + ) + for _, i := range inputs { + value, ok := i.Unpack() + if ok && (!isSome || result > value) { + result = value + isSome = true + } + } + if isSome { + return Some(result) + } else { + return None[T]() + } +} diff --git a/options/options_test.go b/options/options_test.go index caeb303..84a61da 100644 --- a/options/options_test.go +++ b/options/options_test.go @@ -29,3 +29,43 @@ func TestMap(t *testing.T) { AssertEqual(t, Map(None[int](), strconv.Itoa), None[string]()) AssertEqual(t, Map(Some(42), strconv.Itoa), Some("42")) } + +func TestMax(t *testing.T) { + AssertEqual(t, Max[int](), None[int]()) + AssertEqual(t, Max(None[int]()), None[int]()) + AssertEqual(t, Max(None[int](), None[int]()), None[int]()) + + AssertEqual(t, Max(Some(5)), Some(5)) + AssertEqual(t, Max(Some(5), None[int]()), Some(5)) + AssertEqual(t, Max(None[int](), Some(5)), Some(5)) + + AssertEqual(t, Max(Some(5), Some(23)), Some(23)) + AssertEqual(t, Max(None[int](), Some(5), Some(23)), Some(23)) + AssertEqual(t, Max(Some(5), None[int](), Some(23)), Some(23)) + AssertEqual(t, Max(Some(5), Some(23), None[int]()), Some(23)) + + AssertEqual(t, Max(Some(23), Some(5)), Some(23)) + AssertEqual(t, Max(None[int](), Some(23), Some(5)), Some(23)) + AssertEqual(t, Max(Some(23), None[int](), Some(5)), Some(23)) + AssertEqual(t, Max(Some(23), Some(5), None[int]()), Some(23)) +} + +func TestMin(t *testing.T) { + AssertEqual(t, Min[int](), None[int]()) + AssertEqual(t, Min(None[int]()), None[int]()) + AssertEqual(t, Min(None[int](), None[int]()), None[int]()) + + AssertEqual(t, Min(Some(5)), Some(5)) + AssertEqual(t, Min(Some(5), None[int]()), Some(5)) + AssertEqual(t, Min(None[int](), Some(5)), Some(5)) + + AssertEqual(t, Min(Some(5), Some(23)), Some(5)) + AssertEqual(t, Min(None[int](), Some(5), Some(23)), Some(5)) + AssertEqual(t, Min(Some(5), None[int](), Some(23)), Some(5)) + AssertEqual(t, Min(Some(5), Some(23), None[int]()), Some(5)) + + AssertEqual(t, Min(Some(23), Some(5)), Some(5)) + AssertEqual(t, Min(None[int](), Some(23), Some(5)), Some(5)) + AssertEqual(t, Min(Some(23), None[int](), Some(5)), Some(5)) + AssertEqual(t, Min(Some(23), Some(5), None[int]()), Some(5)) +} |
