From bfb598fbd11432466b485bfe8a0eadceed76bfc8 Mon Sep 17 00:00:00 2001 From: Charles Iliya Krempeaux Date: Wed, 10 Aug 2022 09:18:03 -0700 Subject: [PATCH] =?UTF-8?q?opt.Map()=20=E2=80=94=20I=20would=20prefer=20th?= =?UTF-8?q?at=20map=20be=20a=20method,=20but=20the=20current=20implementat?= =?UTF-8?q?ion=20of=20Go=20generatics=20does=20not=20seem=20to=20support?= =?UTF-8?q?=20that?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- map.go | 47 ++++++++++++++++++++++++++++++++++++ map_test.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 map.go create mode 100644 map_test.go diff --git a/map.go b/map.go new file mode 100644 index 0000000..5717547 --- /dev/null +++ b/map.go @@ -0,0 +1,47 @@ +package opt + +// Map applies the function ‘fn’ to the value inside of the optional-type ‘op’, if the optional-type ‘op’ is holding something, and returns it as a new optional-type. +// If the optional-type ‘op’ is holding nothing, then Map also returns nothing. +// +// For example: +// +// var op opt.Optional[string] = opt.Something("Hello world!") +// +// var result opt.Optional[string] = opt.Map(op, strings.ToUpper) +// +// // result == opt.Something[string]("HELLO WORLD!") +// +// // ... +// +// var op2 opt.Optional[string] = opt.Nothing[string]() +// +// var result2 opt.Optional[string] = opt.Map(op, strings.ToUpper) +// +// // result2 == opt.Nothing[string]() +// +// Or also, for example: +// +// fn := func(s string) int { +// return len(s) +// } +// +// var op opt.Optional[string] = opt.Something("Hello world!") +// +// var result opt.Optional[int] = opt.Map(op, fn) +// +// // result == opt.Something[int](12) +// +// // ... +// +// var op2 opt.Optional[string] = opt.Nothing[string]() +// +// var result2 opt.Optional[int] = opt.Map(op, fn) +// +// // result2 == opt.Nothing[int]() +func Map[T1 any, T2 any](op Optional[T1], fn func(T1)T2) Optional[T2] { + if !op.something { + return Nothing[T2]() + } + + return Something(fn(op.value)) +} diff --git a/map_test.go b/map_test.go new file mode 100644 index 0000000..3116ad7 --- /dev/null +++ b/map_test.go @@ -0,0 +1,69 @@ +package opt_test + +import ( + "github.com/reiver/go-opt" + + "testing" +) + +func TestMap_stringToUint(t *testing.T) { + + tests := []struct{ + Optional opt.Optional[string] + Expected opt.Optional[int] + }{ + { + Optional: opt.Nothing[string](), + Expected: opt.Nothing[int](), + }, + + + + { + Optional: opt.Something(""), + Expected: opt.Something[int](0), + }, + + + + { + Optional: opt.Something("once"), + Expected: opt.Something[int](4), + }, + { + Optional: opt.Something("twice"), + Expected: opt.Something[int](5), + }, + { + Optional: opt.Something("thrice"), + Expected: opt.Something[int](6), + }, + { + Optional: opt.Something("fource"), + Expected: opt.Something[int](6), + }, + } + + for testNumber, test := range tests { + + fn := func(s string) int { + return len(s) + } + + mapped := opt.Map(test.Optional, fn) + + { + expected := test.Expected + actual := mapped + + if expected != actual { + t.Errorf("For test #%d, the actual value is not what was expected.", testNumber) + t.Logf("EXPECTED: (%T) %#v", expected, expected) + t.Logf("ACTUAL: (%T) %#v", actual, actual) + t.Logf("OPTIONAL: (%T), %#v", test.Optional, test.Optional) + /////////////////////// CONTINUE + continue + } + } + } +}