Skip to content

Commit

Permalink
feat(optional,result): update optional, result
Browse files Browse the repository at this point in the history
  • Loading branch information
leaxoy committed Jan 3, 2024
1 parent 121f7cf commit 6993451
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 64 deletions.
45 changes: 23 additions & 22 deletions optional/optional.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@ import (
// Optional is a value that may or may not be present.
type Optional[T any] struct{ data *T }

func (self Optional[T]) String() string {
if self.IsSome() {
return fmt.Sprintf("Some(%+v)", *self.data)
}
return "None"
}

// FromPair returns an Optional from a value.
func FromPair[T any](data T, ok bool) Optional[T] {
if ok {
Expand All @@ -24,25 +17,33 @@ func FromPair[T any](data T, ok bool) Optional[T] {
}

// FromPtr returns an Optional from a value.
func FromPtr[T any](data *T) Optional[T] { return Optional[T]{data: data} }
func FromPtr[T any, P ~*T](data P) Optional[T] { return Optional[T]{data: data} }

Check failure on line 20 in optional/optional.go

View workflow job for this annotation

GitHub Actions / build

cannot use data (variable of type P constrained by ~*T) as type *T in struct literal:

Check failure on line 20 in optional/optional.go

View workflow job for this annotation

GitHub Actions / test

cannot use data (variable of type P constrained by ~*T) as type *T in struct literal:

// Some returns an Optional from a value.
//
// Oops!! We can't restrict T is not pointer type. Holy shit!!!
func Some[T any](data T) Optional[T] { return Optional[T]{data: &data} }

// None returns an Optional from a value.
func None[T any]() Optional[T] { return Optional[T]{} }

func (self Optional[T]) String() string {
if self.IsSome() {
return fmt.Sprintf("Some(%+v)", *self.data)
}
return "None"
}

// IsSome returns true if the Optional is Some.
func (self Optional[T]) IsSome() bool { return self.data != nil }

// IsNone returns true if the Optional is None.
func (self Optional[T]) IsNone() bool { return !self.IsSome() }

// IsSomeAnd returns true if the Optional is Some and satisfies the given predicate.
func (self Optional[T]) IsSomeAnd(predicate func(T) bool) bool {
func (self Optional[T]) IsSomeAnd(f func(T) bool) bool {
if self.IsSome() {
return predicate(*self.data)
return f(*self.data)
}
return false
}
Expand All @@ -56,19 +57,19 @@ func (self Optional[T]) Value() T {
}

// ValueOr returns the Optional if it is Some, otherwise returns the given default value.
func (self Optional[T]) ValueOr(defaultValue T) T {
func (self Optional[T]) ValueOr(v T) T {
if self.IsSome() {
return self.Value()
}
return defaultValue
return v
}

// ValueOrElse returns the Optional if it is Some, otherwise returns the given default value.
func (self Optional[T]) ValueOrElse(defaultFunc func() T) T {
func (self Optional[T]) ValueOrElse(f func() T) T {
if self.IsSome() {
return self.Value()
}
return defaultFunc()
return f()
}

// ValueOrZero returns the Optional if it is Some, otherwise returns the zero value of the type.
Expand Down Expand Up @@ -109,14 +110,14 @@ func (self Optional[T]) OrElse(f func() Optional[T]) Optional[T] {
return f()
}

func (self Optional[T]) IfPresent(consume func(T)) {
func (self Optional[T]) IfPresent(f func(T)) {
if self.IsSome() {
consume(self.Value())
f(self.Value())
}
}

func (self Optional[T]) Filter(fn func(T) bool) Optional[T] {
if self.IsSome() && fn(self.Value()) {
func (self Optional[T]) Filter(f func(T) bool) Optional[T] {
if self.IsSome() && f(self.Value()) {
return Some(self.Value())
}
return None[T]()
Expand All @@ -128,11 +129,11 @@ func (self Optional[T]) Map(f func(T) T) Optional[T] {
}

// MapOr returns None if the option is None, otherwise calls the given function and returns the result.
func (self Optional[T]) MapOr(defaultValue T, f func(T) T) T {
func (self Optional[T]) MapOr(v T, f func(T) T) T {
if self.IsSome() {
return f(self.Value())
}
return defaultValue
return v
}

// MapOrElse returns None if the option is None, otherwise calls the given function and returns the result.
Expand Down Expand Up @@ -189,9 +190,9 @@ func (self Optional[T]) UnmarshalJSON(v []byte) error {

var _ json.Unmarshaler = (*Optional[any])(nil)

func Map[A, B any](opt Optional[A], mapFn func(A) B) Optional[B] {
func Map[A, B any](opt Optional[A], f func(A) B) Optional[B] {
if opt.IsSome() {
return Some(mapFn(opt.Value()))
return Some(f(opt.Value()))
}
return None[B]()
}
Expand Down
3 changes: 2 additions & 1 deletion optional/optional_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package optional_test

import (
"testing"

"github.com/frankban/quicktest"
"github.com/go-board/std/optional"
"testing"
)

func TestCtor(t *testing.T) {
Expand Down
63 changes: 22 additions & 41 deletions result/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,28 @@ type Result[T any] struct {
err error
}

// String implements fmt.Stringer.
func (self Result[T]) String() string {
if self.IsOk() {
return fmt.Sprintf("Ok(%+v)", self.data)
}
return fmt.Sprintf("Err(%+v)", self.err)
}

// FromPair create a new Result from a value or an error.
func FromPair[T any](data T, err error) Result[T] { return Result[T]{data, err} }

// Ok create a new Result from a value.
func Ok[T any](data T) Result[T] { return FromPair(data, nil) }
func Ok[T any](data T) Result[T] { return Result[T]{data: data} }

// Err create a new Result from an error.
func Err[T any](err error) Result[T] {
var ok T
return FromPair(ok, err)
}
func Err[T any](err error) Result[T] { return Result[T]{err: err} }

// Errorf create a new Result from a formatted error.
func Errorf[T any](format string, args ...any) Result[T] {
return Err[T](fmt.Errorf(format, args...))
}

// String implements fmt.Stringer.
func (self Result[T]) String() string {
if self.IsOk() {
return fmt.Sprintf("Ok(%+v)", self.data)
}
return fmt.Sprintf("Err(%+v)", self.err)
}

// IsOk returns true if the Result is Ok.
func (self Result[T]) IsOk() bool { return self.err == nil }

Expand Down Expand Up @@ -77,20 +74,20 @@ func (self Result[T]) Value() T {
}

// ValueOr returns the value of the Result if it is Ok, otherwise return the given value.
func (self Result[T]) ValueOr(defaultValue T) T {
func (self Result[T]) ValueOr(v T) T {
if self.IsOk() {
return self.data
}
return defaultValue
return v
}

// ValueOrElse returns the value of the Result if it is Ok,
// otherwise return the result of calling the given function.
func (self Result[T]) ValueOrElse(defaultFunc func() T) T {
func (self Result[T]) ValueOrElse(f func() T) T {
if self.IsOk() {
return self.data
}
return defaultFunc()
return f()
}

// ValueOrZero returns the value of the Result if it is Ok,
Expand All @@ -112,25 +109,16 @@ func (self Result[T]) Error() error {
}

// IfOk call the function if the Result is Ok.
func (self Result[T]) IfOk(consume func(T)) {
func (self Result[T]) IfOk(f func(T)) {
if self.IsOk() {
consume(self.Value())
f(self.Value())
}
}

// IfErr call the function if the Result is Err.
func (self Result[T]) IfErr(consume func(error)) {
if self.IsErr() {
consume(self.Error())
}
}

// Match call onOk if the Result is Ok, otherwise call onErr.
func (self Result[T]) Match(onOk func(T), onErr func(error)) {
func (self Result[T]) IfErr(f func(error)) {
if self.IsErr() {
onErr(self.err)
} else {
onOk(self.data)
f(self.Error())
}
}

Expand All @@ -144,16 +132,9 @@ func (self Result[T]) AsRawParts() (data T, err error) {
return
}

func Map[A, B any](result Result[A], transformer func(A) B) Result[B] {
if result.IsOk() {
return Ok(transformer(result.Value()))
}
return Err[B](result.Error())
}

func Flatten[A any](result Result[Result[A]]) Result[A] {
if result.IsOk() {
return result.data
func Map[T, U any](res Result[T], f func(T) U) Result[U] {
if res.IsOk() {
return Ok(f(res.data))
}
return Err[A](result.err)
return Err[U](res.err)
}

0 comments on commit 6993451

Please sign in to comment.