diff --git a/option.go b/option.go new file mode 100644 index 0000000..4719baa --- /dev/null +++ b/option.go @@ -0,0 +1,47 @@ +package gonads + +import "errors" + +var ( + ErrOptionIsNone = errors.New("gonads: Option[T] has no value") +) + +// Option is a container that might contain a value. +type Option[T any] struct { + val *T +} + +// IsSome returns true if the Option has some value in it. +func (o Option[T]) IsSome() bool { + return o.val != nil +} + +// IsNone returns true if the Option has no value in it. +func (o Option[T]) IsNone() bool { + return !o.IsSome() +} + +// Take a value out of the option if it exists. +func (o Option[T]) Take() (*T, error) { + if o.IsNone() { + return nil, ErrOptionIsNone + } + + return o.val, nil +} + +// Set the value of the option to a given value. +func (o *Option[T]) Set(val T) { + o.val = &val +} + +// Clear removes the value from an Option. +func (o *Option[T]) Clear() { + o.val = nil +} + +// NewOption creates a new Option with the given type. All Options +// Start out as nil. +func NewOption[T any]() *Option[T] { + return &Option[T]{} +} diff --git a/option_test.go b/option_test.go new file mode 100644 index 0000000..9b604f8 --- /dev/null +++ b/option_test.go @@ -0,0 +1,24 @@ +package gonads + +import ( + "testing" +) + +func TestOption(t *testing.T) { + o := NewOption[string]() + val, err := o.Take() + if err == nil { + t.Fatalf("[unexpected] wanted no value out of Option[T], got: %v", val) + } + + o.Set("hello friendos") + _, err = o.Take() + if err != nil { + t.Fatalf("[unexpected] wanted no value out of Option[T], got: %v", err) + } + + o.Clear() + if o.IsSome() { + t.Fatal("Option should have none, but has some") + } +}