Skip to content

Instantly share code, notes, and snippets.

@tappoz
Last active March 13, 2018 10:29
Show Gist options
  • Save tappoz/24122423140ad7594e270d50b7b5e98b to your computer and use it in GitHub Desktop.
Save tappoz/24122423140ad7594e270d50b7b5e98b to your computer and use it in GitHub Desktop.
First class functions in Go

First class functions in go

This is a minimum working example to explore the usage of first class functions as presented by Dave Cheney.

(On the same topic Rob Pike also wrote an interesting article: https://commandcenter.blogspot.co.uk/2014/01/self-referential-functions-and-design.html)

package boom

import (
	"math"
	"testing"
)

// Calculator is the struct containing the accumulator (the state)
type Calculator struct {
	acc float64
}

// Opfunc is the function type representing the operation to be performed
type Opfunc func(float64) float64

// Do performs an operation on the function type Opfunc
func (c *Calculator) Do(op Opfunc) float64 {
	c.acc = op(c.acc)
	return c.acc
}

// Add allows the flexibility to pass some input parameters to be combined
// inside Opfunc
func Add(n float64) Opfunc {
	return func(acc float64) float64 {
		return acc + n
	}
}

// Sqrt is providing an implementation of Opfunc without the need
// to pass any input parameter
func Sqrt() Opfunc {
	return func(n float64) float64 {
		return math.Sqrt(n)
	}
}

// Compose iterates over the variadic input to apply all the Opfunc implementations
func (c *Calculator) Compose(ops ...Opfunc) {
	for _, op := range ops {
		c.Do(op)
	}
}

func TestDo(t *testing.T) {
	var c Calculator
	c.Do(Add(2))
	c.Do(Sqrt())

	if c.acc < 1.41421356237 {
		t.Error("AAAHHH!!!")
	}
}

func TestCompose(t *testing.T) {
	var c Calculator
	c.Compose(Add(2), Sqrt())

	if c.acc < 1.41421356237 {
		t.Error("AAAHHH!!!")
	}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment