Go Example Inspired by Lambda CalculusΒΆ

The following code example shows that Go avoids capturing free variables in closures.

package main

import "fmt"

// Notice here that the variable a is defined as a local variable inside f,
// and is also used inside the anonymous function that is returned. Thus f
// returns a closure.
func f(n int) func() int {
    a := 3
    return func() int {
        return n + a
    }
}

// If a was not defined locally, then we'd get a compiler error, e.g. this
// function doesn't compile in Go:
//
//    func f(n int) func() int {
//        return func() int {
//            return n + a  // compiler error: a undefined
//        }
//    }
//

// Here, g ha a local variable named a. What happens if f has a free variable
// named a? Does it use the value of a defined here, i.e. 5? Answer: no, the
// passed-in function f does not use the a in g. That would be a kind of
// variable capture that we could, in general, not predict! You often have no
// idea of the names of the local variables in a function, so if the free
// variables in a passed-in function were captured, you could get undefined
// and unexpected behaviour.
func g(f func() int) {
    a := 5
    fmt.Println("a =", a)
    fmt.Println(f())
}

func main() {
    add := f(5)
    fmt.Println(add()) // prints 8
    g(add)             // a = 5, 8
}