Sunday, December 30, 2012

go(ing) under

Lots of people like go and this year I began to find it unavoidable - I'm even ending the year with go being the main language that helps pay my bills!

One of the things that go lets you do is pass functions around.
I started the year talking about under from the j language. Which lets you 'bookend' some function with another function (a verb) and a function which undoes that function (obverse).
A great example is Pythagoras' theorem:
  1. You perform some 'pre-processing' on each value (squaring)
  2. You add all the values up
  3. You square root the result
I started the year talking about under in clojure. Here it is implemented in go. Complete with functions being passed around, closures, and functions returning functions. Happy new year!
package main
import (
"fmt"
"math"
)
//Setup some types for functions we want to pass around
type unaryFloat func(float64) float64
type binaryFloat func(float64, float64) float64
//A wrapper around + that will let us pass it around
func passableAdd(x, y float64) float64 {
return x + y
}
//This is the magical under function.
//Call some function on each value (verb)
//Combine these new values in another function (fn)
//Undo the verb (obverse)
func under(verb, obverse unaryFloat, fn binaryFloat, x, y float64) float64 {
return obverse(fn(verb(x), verb(y)))
}
//We want to make functions that call math.Pow to an exponent that we specify.
//square = makePower(2)
//cubing = makePower(3)
func makePower(exp float64) func(float64) float64 {
f := func(x float64) float64 {
return math.Pow(x, exp)
}
return f
}
//My favourite demonstration of under. Pythagoras theorem
func pythag(x, y float64) float64 {
sq := makePower(2)
return under(sq, math.Sqrt, passableAdd, x, y)
}
func main() {
fmt.Println(pythag(3, 4))
}
view raw under.go hosted with ❤ by GitHub