-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
421 additions
and
479 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
module github.com/its-felix/shine | ||
module github.com/its-felix/shine/v1 | ||
|
||
go 1.19 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,221 +1,27 @@ | ||
package shine | ||
|
||
type Option[T any] struct { | ||
some bool | ||
v T | ||
type Option[T any] interface { | ||
IsSome() bool | ||
IsNone() bool | ||
Expect(panicV any) T | ||
Unwrap() T | ||
UnwrapOr(def T) T | ||
UnwrapOrDefault() T | ||
UnwrapOrElse(fn func() T) T | ||
OkOr(err error) Result[T, error] | ||
OkOrElse(fn func() error) Result[T, error] | ||
Filter(predicate func(v T) bool) Option[T] | ||
Map(fn func(v T) T) Option[T] | ||
AndThen(fn func(v T) Option[T]) Option[T] | ||
OrElse(fn func() Option[T]) Option[T] | ||
Xor(other Option[T]) Option[T] | ||
Iter() <-chan T | ||
} | ||
|
||
// OMap invokes the given function to transform the value of this Option if it represents a Some and returns a new Some; returns None for None | ||
func OMap[T any, E any](o Option[T], fnc func(T) E) Option[E] { | ||
if o.IsSome() { | ||
return NewSome(fnc(o.Unwrap())) | ||
} else { | ||
return NewNone[E]() | ||
} | ||
} | ||
|
||
// Zip returns a new Option with both given Options values if both are Some; returns None if any of the two is None | ||
func Zip[T any, E any](o1 Option[T], o2 Option[E]) Option[Tuple[T, E]] { | ||
return ZipWith(o1, o2, func(t T, e E) Tuple[T, E] { | ||
return Tuple[T, E]{o1.Unwrap(), o2.Unwrap()} | ||
}) | ||
} | ||
|
||
// ZipWith invokes the given function to form a value for a new Option if both are Some; returns None if any of the two is None | ||
func ZipWith[T any, E any, O any](o1 Option[T], o2 Option[E], zip func(T, E) O) Option[O] { | ||
if o1.IsSome() && o2.IsSome() { | ||
return NewSome(zip(o1.Unwrap(), o2.Unwrap())) | ||
} else { | ||
return NewNone[O]() | ||
} | ||
} | ||
|
||
// OAndThen invokes the given function to form a new Option if the given Option is Some; returns None for None | ||
func OAndThen[T any, E any](o Option[T], fnc func(T) Option[E]) Option[E] { | ||
if o.IsSome() { | ||
return fnc(o.Unwrap()) | ||
} else { | ||
return NewNone[E]() | ||
} | ||
} | ||
|
||
// IsSome returns true if this Option represents a Some | ||
func (o Option[T]) IsSome() bool { | ||
return o.some | ||
} | ||
|
||
// IsNone returns true if this Option represents a None | ||
func (o Option[T]) IsNone() bool { | ||
return !o.some | ||
} | ||
|
||
// Expect returns this Option underlying value if it represents a Some; panics with the given message otherwise | ||
func (o Option[T]) Expect(msg string) T { | ||
if !o.some { | ||
panic(msg) | ||
} | ||
|
||
return o.v | ||
} | ||
|
||
// Unwrap returns this Option underlying value if it represents a Some; panics with a generic message otherwise | ||
func (o Option[T]) Unwrap() T { | ||
if !o.some { | ||
panic("Unwrap on None") | ||
} | ||
|
||
return o.v | ||
} | ||
|
||
// UnwrapOr returns this Option underlying value if it represents a Some; returns the given default value otherwise | ||
func (o Option[T]) UnwrapOr(def T) T { | ||
if o.some { | ||
return o.v | ||
} else { | ||
return def | ||
} | ||
} | ||
|
||
// UnwrapOrDefault returns this Option underlying value if it represents a Some; returns the default value for this type otherwise | ||
func (o Option[T]) UnwrapOrDefault() T { | ||
if o.some { | ||
return o.v | ||
} else { | ||
var def T | ||
return def | ||
} | ||
} | ||
|
||
// UnwrapOrElse returns this Option underlying value if it represents a Some; returns the result of invoking the given function otherwise | ||
func (o Option[T]) UnwrapOrElse(fnc func() T) T { | ||
if o.some { | ||
return o.v | ||
} else { | ||
return fnc() | ||
} | ||
} | ||
|
||
// OkOr returns this Option underlying value as a Result (Ok) if it represents a Some; returns a Result (Err) with the given error otherwise | ||
func (o Option[T]) OkOr(e error) Result[T] { | ||
if o.some { | ||
return NewOk[T](o.v) | ||
} else { | ||
return NewErr[T](e) | ||
} | ||
} | ||
|
||
// OkOrElse returns this Option underlying value as a Result (Ok) if it represents a Some; returns a Result (Err) with the error returned by the given function otherwise | ||
func (o Option[T]) OkOrElse(fnc func() error) Result[T] { | ||
if o.some { | ||
return NewOk[T](o.v) | ||
} else { | ||
return NewErr[T](fnc()) | ||
} | ||
} | ||
|
||
// Filter returns this Option unmodified if it represents a Some and the given function returns true given the value; returns Option (None) otherwise | ||
func (o Option[T]) Filter(fnc func(T) bool) Option[T] { | ||
if o.some && fnc(o.v) { | ||
return o | ||
} else { | ||
return NewNone[T]() | ||
} | ||
} | ||
|
||
// Iter returns a channel with this Option underlying value if it represents a Some; returns an empty channel otherwise | ||
func (o Option[T]) Iter() <-chan T { | ||
ch := make(chan T, 1) | ||
|
||
if o.some { | ||
ch <- o.v | ||
} | ||
|
||
close(ch) | ||
|
||
return ch | ||
} | ||
|
||
// Map invokes the given function to transform the value of this Option is it's Some and returns a new Some; returns None for None | ||
func (o Option[T]) Map(fnc func(T) T) Option[T] { | ||
if o.some { | ||
return NewSome(fnc(o.v)) | ||
} else { | ||
return NewNone[T]() | ||
} | ||
} | ||
|
||
// MapAny invokes the given function to transform the value of this Option is it's Some and returns a new Some; returns None for None | ||
func (o Option[T]) MapAny(fnc func(T) any) Option[any] { | ||
if o.some { | ||
return NewSome(fnc(o.v)) | ||
} else { | ||
return NewNone[any]() | ||
} | ||
} | ||
|
||
// AndThen invokes the given function to form a new Option if the given Option is Some; returns None for None | ||
func (o Option[T]) AndThen(fnc func(T) Option[T]) Option[T] { | ||
if o.some { | ||
return fnc(o.v) | ||
} else { | ||
return NewNone[T]() | ||
} | ||
} | ||
|
||
// AndThenAny invokes the given function to form a new Option if the given Option is Some; returns None for None | ||
func (o Option[T]) AndThenAny(fnc func(T) Option[any]) Option[any] { | ||
if o.some { | ||
return fnc(o.v) | ||
} else { | ||
return NewNone[any]() | ||
} | ||
} | ||
|
||
// OrElse returns this Option unmodified if it represents a Some; returns the result of invoking the given function otherwise | ||
func (o Option[T]) OrElse(fnc func() Option[T]) Option[T] { | ||
if o.some { | ||
return o | ||
} else { | ||
return fnc() | ||
} | ||
} | ||
|
||
// ZipAny returns a new Option with both given Options values if both are Some; returns None if any of the two is None | ||
func (o Option[T]) ZipAny(other Option[any]) Option[[2]any] { | ||
if o.some { | ||
return NewSome([2]any{o.v, other.v}) | ||
} else { | ||
return NewNone[[2]any]() | ||
} | ||
} | ||
|
||
// ZipWithAny invokes the given function to form a value for a new Option if both are Some; returns None if any of the two is None | ||
func (o Option[T]) ZipWithAny(other Option[any], fnc func(T, any) [2]any) Option[[2]any] { | ||
if o.some { | ||
return NewSome(fnc(o.v, other.v)) | ||
} else { | ||
return NewNone[[2]any]() | ||
} | ||
} | ||
|
||
// NewOption returns an Option (Some) with the given pointers value if it's not nil; returns Option (None) otherwise | ||
func NewOption[T any](v *T) Option[T] { | ||
if v == nil { | ||
return NewNone[T]() | ||
} else { | ||
return NewSome(*v) | ||
} | ||
} | ||
|
||
// NewSome returns an Option (Some) with the given value | ||
func NewSome[T any](v T) Option[T] { | ||
return Option[T]{ | ||
some: true, | ||
v: v, | ||
} | ||
} | ||
|
||
// NewNone returns an Option (None) | ||
func NewNone[T any]() Option[T] { | ||
return Option[T]{} | ||
return NewSome(*v) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package shine | ||
|
||
type None[T any] struct{} | ||
|
||
func (n None[T]) IsSome() bool { | ||
return false | ||
} | ||
|
||
func (n None[T]) IsNone() bool { | ||
return true | ||
} | ||
|
||
func (n None[T]) Expect(panicV any) T { | ||
panic(panicV) | ||
} | ||
|
||
func (n None[T]) Unwrap() T { | ||
panic("Unwrap on None") | ||
} | ||
|
||
func (n None[T]) UnwrapOr(def T) T { | ||
return def | ||
} | ||
|
||
func (n None[T]) UnwrapOrDefault() T { | ||
var def T | ||
return def | ||
} | ||
|
||
func (n None[T]) UnwrapOrElse(fn func() T) T { | ||
return fn() | ||
} | ||
|
||
func (n None[T]) OkOr(err error) Result[T, error] { | ||
return NewErr[T](err) | ||
} | ||
|
||
func (n None[T]) OkOrElse(fn func() error) Result[T, error] { | ||
return NewErr[T](fn()) | ||
} | ||
|
||
func (n None[T]) Filter(predicate func(v T) bool) Option[T] { | ||
return n | ||
} | ||
|
||
func (n None[T]) Map(fn func(v T) T) Option[T] { | ||
return n | ||
} | ||
|
||
func (n None[T]) AndThen(fn func(v T) Option[T]) Option[T] { | ||
return n | ||
} | ||
|
||
func (n None[T]) OrElse(fn func() Option[T]) Option[T] { | ||
return fn() | ||
} | ||
|
||
func (n None[T]) Xor(other Option[T]) Option[T] { | ||
if other, ok := other.(Some[T]); ok { | ||
return other | ||
} | ||
|
||
return n | ||
} | ||
|
||
func (n None[T]) Iter() <-chan T { | ||
ch := make(chan T) | ||
close(ch) | ||
|
||
return ch | ||
} | ||
|
||
func NewNone[T any]() None[T] { | ||
return None[T]{} | ||
} | ||
|
||
var _ Option[struct{}] = NewNone[struct{}]() |
Oops, something went wrong.