add thunk type

Signed-off-by: Xe Iaso <me@christine.website>
This commit is contained in:
Cadey Ratio 2022-04-24 17:21:57 +00:00
parent 9804c6b7b0
commit 550ad6721e
3 changed files with 77 additions and 4 deletions

View File

@ -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
}
// 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
return *o.val, nil
}
// Set the value of the option to a given value.

31
thunk.go Normal file
View File

@ -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()
}

32
thunk_test.go Normal file
View File

@ -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))
}