Skip to content

Commit

Permalink
Add docs; change Take's signature
Browse files Browse the repository at this point in the history
  • Loading branch information
oissevalt committed Mar 17, 2024
1 parent db62759 commit 68201dc
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 12 deletions.
19 changes: 16 additions & 3 deletions chained.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ func ChainedNone[T any]() Optional[T] {
return &Chained[T]{empty: true, checkptr: ok}
}

// IsNone reports whether the current optional contains no value, merely
// a nil pointer, or nested pointers to a nil reference.
func (s *Chained[T]) IsNone() bool {
if s.empty || s.inner == nil {
return true
Expand All @@ -58,20 +60,27 @@ func (s *Chained[T]) IsNone() bool {
}
}

// Value attempts to retrieve the contained value. If the optional contains no value,
// is a nil pointer, or nested pointers to nil, it will return ErrNoneOptional.
func (s *Chained[T]) Value() (t T, err error) {
if s.IsNone() {
return t, ErrNoneOptional
}
return *s.inner, nil
}

// Must returns the contained value, panicking if the optional is None.
func (s *Chained[T]) Must() T {
if s.IsNone() {
panic(ErrNoneOptional)
}
return *s.inner
}

// Swap swaps the contained value with v, returning the original value. If v is
// a nil pointer, the current optional will be set to None. Whether the
// returned value is valid is not guaranteed; if the optional is previously None,
// it can be the zero value of the type, or nil.
func (s *Chained[T]) Swap(v T) (t T) {
if !s.IsNone() {
t = *s.inner
Expand All @@ -97,15 +106,19 @@ func (s *Chained[T]) Swap(v T) (t T) {
return
}

func (s *Chained[T]) Take() (t T, err error) {
// Take moves the inner value out, leaving the optional in a None state.
// It returns a reference to the contained value, if any. Should the optional
// previously be None, ErrNoneOptional is returned.
func (s *Chained[T]) Take() (*T, error) {
if s.IsNone() {
return t, ErrNoneOptional
return nil, ErrNoneOptional
}
p := s.inner
s.inner, s.empty = nil, true
return *p, nil
return p, nil
}

// With executes the given closure with the contained value, if it is not None.
func (s *Chained[T]) With(f func(T)) {
if !s.IsNone() {
f(*s.inner)
Expand Down
2 changes: 1 addition & 1 deletion opzione.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type Optional[T interface{}] interface {

// Take attempts to move out the optional's inner value, leaving a
// None behind. If the optional is None, it returns ErrNoneOptional.
Take() (t T, err error)
Take() (*T, error)

// With accepts a closure which will be executed with the optional's
// inner value, if it is Some.
Expand Down
8 changes: 4 additions & 4 deletions opzione_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ func TestValueOptional(t *testing.T) {
expect("10", t, err, nil)
expect("11", t, value, 15)

value, err = someValue.Take()
value2, err := someValue.Take()
expect("12", t, err, nil)
expect("13", t, value, 23)
expect("13", t, *value2, 23)
expect("14", t, someValue.IsNone(), true)
}

Expand Down Expand Up @@ -118,9 +118,9 @@ func TestPointerOptional(t *testing.T) {
expect("10", t, err, nil)
expect("11", t, value, &value1)

value, err = somePointer.Take()
value3, err := somePointer.Take()
expect("12", t, err, nil)
expect("13", t, value, &value2)
expect("13", t, *value3, &value2)
expect("14", t, somePointer.IsNone(), true)

swapped = somePointer.Swap(nil)
Expand Down
22 changes: 18 additions & 4 deletions simple.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,33 @@ func SimpleNone[T interface{}]() *Simple[T] {
return &Simple[T]{empty: true, ptrtyp: ok}
}

// IsNone reports whether the current optional contains no value, or merely
// a nil pointer.
func (s *Simple[T]) IsNone() bool {
return s.empty || s.v == nil
}

// Value attempts to retrieve the contained value. If the optional contains no value,
// it will return ErrNoneOptional.
func (s *Simple[T]) Value() (t T, err error) {
if s.IsNone() {
return t, ErrNoneOptional
}
return *s.v, nil
}

// Must returns the contained value, panicking if the optional is None.
func (s *Simple[T]) Must() T {
if s.IsNone() {
panic(ErrNoneOptional)
}
return *s.v
}

// Swap swaps the contained value with v, returning the original value. If v is
// a nil pointer, the current optional will be set to None. Whether the
// returned value is valid is not guaranteed; if the optional is previously None,
// it can be the zero value of the type, or nil.
func (s *Simple[T]) Swap(v T) (t T) {
if !s.IsNone() {
t = *s.v
Expand All @@ -62,23 +71,28 @@ func (s *Simple[T]) Swap(v T) (t T) {
if s.ptrtyp {
ptr, _ := isptr(v)
if ptr == nil {
panic("nil pointer cannot be used to construct Some")
s.v, s.empty = nil, true
return
}
}

s.v, s.empty = &v, false
return
}

func (s *Simple[T]) Take() (t T, err error) {
// Take moves the inner value out, leaving the optional in a None state.
// It returns a reference to the contained value, if any. Should the optional
// previously be None, ErrNoneOptional is returned.
func (s *Simple[T]) Take() (*T, error) {
if s.IsNone() {
return t, ErrNoneOptional
return nil, ErrNoneOptional
}
t = *s.v
t := s.v
s.v, s.empty = nil, true
return t, nil
}

// With executes the given closure with the contained value, if it is not None.
func (s *Simple[T]) With(f func(T)) {
if !s.IsNone() {
f(*s.v)
Expand Down

0 comments on commit 68201dc

Please sign in to comment.