I had the opportunity to work with the Go programming language about a month ago. Since I prefer functional programming over object oriented programming I wanted to see if I could create things like closures and first class functions. It turns out all of this is possible in Go. In this post we will write a function that takes function as one of its arguments and invokes the function on every element of an array (much like the map function). Then we will create a closure by defining a function within a function and use the closure to hoist a variable up into scope of the parent function. In the end we can combine the two functions into some code that computes the sum of all numbers in an array. The code in this post is meant to showcase Go’s closures and first class functions. There are much easier ways of summing the values of all the numbers in an array than this. If you need the sum of all the numbers in an array just write a for loop that adds each of the numbers to a sum variable one by one.
The since the first function takes another function and applies it to each item in an array we will can call it ApplyToArray
. The complete function is below:
func ApplyToArray(fun func(int) error, numbers []int) (err error) {
for i := 0; i < len(numbers); i++ {
err := fun(numbers[i])
if err != nil {
return err
}
}
return nil
}
The first thing to note about this function are the arguments that it expects. The first argument must be a function that takes an integer and returns an error (fun func(int) error
) and second is an array of integers. The function that is passed in is bound to the fun
variable in the function. The body of the functions is simply a for loop that iterates over all the numbers in the numbers
array. Inside the for loop the function that was passed in (fun
) is invoked on each number. Since the return value is an error we check to see if the error is nil. If the error is not nil we stop iteration and return the error. Otherwise the loop continues. This allows us to pass any function in and have it invoked with each element in the array, but due to Go’s strongly typed nature it limits what the array can contain and what types function passed in must receive and return. The ApplyToarray
function above will only be able to handle a function that expects an integer and an array containing integers as arguments. Anything else will raise an exception.
Now that we have our ApplyToArray
function complete let’s build a function that computes the sum of all the values in an array. As you probably noticed the ApplyToArray
function invokes the given function with every element in the array, but it doesn’t provide a way for the function that is passed in (sum
) to return an intermediate value and pass it to the next invocation of the sum
function. We can easily get around this by using a closure to “hoist” the variable out to the sum
function we pass into the ApplyToArray
function. We will call this new function Sum
. Here is the complete Sum
function:
func Sum(numbers []int) (sum int) {
sum = 0
fun := func(number int) (err error) {
sum = sum + number
return nil
}
ApplyToArray(fun, numbers)
return sum
}
Inside Sum
we set the sum
variable to 0 and then create a function and assign it to the variable fun
. fun
expects an integer as it’s only argument, so it matches the type specified for the first argument of ApplyToArray
. Inside fun
is where things get more interesting. We take the number passed in and add it to the sum
variable. Then we assign the result of the addition back to the sum
variable. But the sum
variable is not defined inside fun
. It is defined outside fun
in the Sum
function. Since the variable sum is not defined inside fun
we are actually referencing the sum
variable defined in the Sum
function scope. The fun
function we defined inherited the scope of its parent function and that allows us to make changes to sum
from inside fun
. This means that if we were to invoke fun
with the integer 1
the value of the sum
variable inside the Sum
function would equal 1
as well. This is variable hoisting.
After defining the fun
function in Sum
we invoke ApplyToArray
with fun
and the array of numbers. Once ApplyToArray
returns the sum
variable contains the sum of all the integers in the numbers
array, which we simply return to the caller of the function.
The complete example code using both functions looks like this:
package main
import "fmt"
func main() {
sum := Sum(numbers)
fmt.Println(sum)
}
func Sum(numbers []int) (sum int) {
sum = 0
fun := func(number int) (err error) {
sum = sum + number
return nil
}
ApplyToArray(fun, numbers)
return sum
}
func ApplyToArray(fun func(int) error, numbers []int) (err error) {
for i := 0; i < len(numbers); i++ {
err := fun(numbers[i])
if err != nil {
return err
}
}
return nil
}
It’s nice to see that see things like first class functions are present in a newer compiled language like Go. While I don’t think I will be using Go very often on projects in the future I enjoyed learning it and it was definitely worth it. Check it out at golang.org.
If you have any questions feel free to email me.