35 lines
807 B
Go
35 lines
807 B
Go
package fun
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"github.com/BurntSushi/ty"
|
|
)
|
|
|
|
// Memo has a parametric type:
|
|
//
|
|
// func Memo(f func(A) B) func(A) B
|
|
//
|
|
// Memo memoizes any function of a single argument that returns a single value.
|
|
// The type `A` must be a Go type for which the comparison operators `==` and
|
|
// `!=` are fully defined (this rules out functions, maps and slices).
|
|
func Memo(f interface{}) interface{} {
|
|
chk := ty.Check(
|
|
new(func(func(ty.A) ty.B)),
|
|
f)
|
|
vf := chk.Args[0]
|
|
|
|
saved := make(map[interface{}]reflect.Value)
|
|
memo := func(in []reflect.Value) []reflect.Value {
|
|
val := in[0].Interface()
|
|
ret, ok := saved[val]
|
|
if ok {
|
|
return []reflect.Value{ret}
|
|
}
|
|
|
|
ret = call1(vf, in[0])
|
|
saved[val] = ret
|
|
return []reflect.Value{ret}
|
|
}
|
|
return reflect.MakeFunc(vf.Type(), memo).Interface()
|
|
}
|