tl;dr: I did lazy evaluation in go
A small pattern that is usefull for some algorithms is lazy evaluation. Haskell is famous for making extensive use of it. One way to emulate goroutine-safe lazy evaluation is using closures and the sync-package:
type LazyInt func() int
func Make(f func() int) LazyInt {
var v int
var once sync.Once
return func() int {
once.Do(func() {
v = f()
f = nil // so that f can now be GC'ed
})
return v
}
}
func main() {
n := Make(func() { return 23 }) // Or something more expensive…
fmt.Println(n()) // Calculates the 23
fmt.Println(n() + 42) // Reuses the calculated value
}
This is not the fastest possible code, but it already has less overhead than one would think (and it is pretty simple to deduce a faster implementation from this). I have implemented a simple command, that generates these implementations (or rather, more optimized ones based on the same idea) for different types.
This is of course just the simplest use-case for lazynes. In practice, you might also want Implementations of Expressions
func LazyAdd(a, b LazyInt) LazyInt {
return Make(func() { return a() + b() })
}
or lazy slices (slightly more complicated to implement, but possible) but I left that for a later improvement of the package (plus, it makes the already quite big API even bigger) :)