add thunk type
Signed-off-by: Xe Iaso <me@christine.website>
This commit is contained in:
parent
9804c6b7b0
commit
550ad6721e
18
option.go
18
option.go
|
@ -21,13 +21,23 @@ 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) {
|
||||
// Yank will pull a value out of an option, panicking if it doesn't exist.
|
||||
func (o Option[T]) Yank() T {
|
||||
if o.IsNone() {
|
||||
return nil, ErrOptionIsNone
|
||||
panic("gonads: Yank on None Option")
|
||||
}
|
||||
|
||||
return o.val, nil
|
||||
return *o.val
|
||||
}
|
||||
|
||||
// Take a value out of the option if it exists.
|
||||
func (o Option[T]) Take() (T, error) {
|
||||
if o.IsNone() {
|
||||
var zero T
|
||||
return zero, ErrOptionIsNone
|
||||
}
|
||||
|
||||
return *o.val, nil
|
||||
}
|
||||
|
||||
// Set the value of the option to a given value.
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package gonads
|
||||
|
||||
// Thunk contains a partially computed value. This thunk is also lazy because
|
||||
// it will only run the underlying thunked action _once_ and then return the
|
||||
// result of that action, caching it for further use.
|
||||
//
|
||||
// If this is confusing to you, consider the following JavaScript:
|
||||
//
|
||||
// let add = (x, y) => x + y;
|
||||
// let addCurr = (x) => (y) => x + y;
|
||||
// console.log(add(2, 2)); // 4
|
||||
// console.log(addCurr(2)(2)); // 4
|
||||
// let addTwo = addCurr(2); // (y) => 2 + y;
|
||||
//
|
||||
// In this example, `addTwo` is a thunk that contains a partially applied addCurr
|
||||
// invocation.
|
||||
type Thunk[T any] struct {
|
||||
doer func(T) T // action being thunked
|
||||
o Option[T] // cache for complete thunk data
|
||||
}
|
||||
|
||||
// Force evaluates a Thunk's action if it needs to, otherwise it returns the
|
||||
// previously evaluated result.
|
||||
func (t Thunk[T]) Force(inp T) T {
|
||||
if t.o.IsSome() {
|
||||
return t.o.Yank()
|
||||
}
|
||||
|
||||
t.o.Set(t.doer(inp))
|
||||
return t.o.Yank()
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package gonads
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Fib(n int) int {
|
||||
if n <= 1 {
|
||||
return n
|
||||
}
|
||||
return Fib(n-1) + Fib(n-2)
|
||||
}
|
||||
|
||||
func TestRecurFib(t *testing.T) {
|
||||
t.Log(Fib(40))
|
||||
}
|
||||
|
||||
func TestThunkFib(t *testing.T) {
|
||||
cache := make([]Thunk[int], 41)
|
||||
cache[0].o.Set(0)
|
||||
cache[1].o.Set(1)
|
||||
|
||||
fib := func(n int) int {
|
||||
return cache[n-1].Force(n-1) + cache[n-2].Force(n-2)
|
||||
}
|
||||
|
||||
for i := range cache {
|
||||
cache[i].doer = fib
|
||||
}
|
||||
|
||||
t.Log(cache[40].Force(40))
|
||||
}
|
Loading…
Reference in New Issue