package gonads import "errors" var ( ErrOptionIsNone = errors.New("gonads: Option value contains nothing") ) // Option is a container that might contain a value. type Option[T any] struct { val *T } // IsSome returns true if the option contains a value. func (o Option[T]) IsSome() bool { return o.val != nil } // IsNone returns false if the option does not contain a value. func (o Option[T]) IsNone() bool { return !o.IsSome() } // Take safely fetches the value from the Option. func (o Option[T]) Take() (*T, error) { if o.IsNone() { return nil, ErrOptionIsNone } return o.val, nil } // Set assigns a value to an Option. func (o *Option[T]) Set(val *T) { o.val = val } func NewOption[T any](val *T) Option[T] { return Option[T]{val: val} } // Thunk represents an uncomputed value that is cached for faster use later. type Thunk[T any] struct { o Option[T] doer func() *T } // Force either returns the cached thunk value or computes it and caches the result. func (t Thunk[T]) Force() *T { if t.o.IsSome() { return t.o.val } t.o.Set(t.doer()) return t.o.val } func NewThunk[T any](doer func() *T) Thunk[T] { return Thunk[T]{ o: NewOption[T](nil), doer: doer, } }