Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

First class functions in Go

People also ask

Are functions first class in Go?

In Go you can assign functions to variables, pass functions to functions, and even write functions that return functions. Functions are first-class—they work in all the places that integers, strings, and other types work.

Can you pass a function as a parameter in Go?

Golang supports two different ways to pass arguments to the function i.e. Pass by Value or Call by Value and Pass By Reference or Call By Reference. By default, Golang uses the call by value way to pass the arguments to the function.

What does it mean when a language treats functions as first class citizens?

A programming language is said to have First-class functions when functions in that language are treated like any other variable. For example, in such a language, a function can be passed as an argument to other functions, can be returned by another function and can be assigned as a value to a variable.

Does Go have higher order functions?

From a functional-programming point of view, Golang supports higher-order functions.


Go Language and Functional Programming might help. From this blog post:

package main
import fmt "fmt"
type Stringy func() string
func foo() string{
        return "Stringy function"
}
func takesAFunction(foo Stringy){
    fmt.Printf("takesAFunction: %v\n", foo())
}
func returnsAFunction()Stringy{
    return func()string{
        fmt.Printf("Inner stringy function\n");
        return "bar" // have to return a string to be stringy
    }
}
func main(){
    takesAFunction(foo);
    var f Stringy = returnsAFunction();
    f();
    var baz Stringy = func()string{
        return "anonymous stringy\n"
    };
    fmt.Printf(baz());
}

Author is the blog owner: Dethe Elza (not me)


package main

import (
    "fmt"
)

type Lx func(int) int

func cmb(f, g Lx) Lx {
    return func(x int) int {
        return g(f(x))
    }
}

func inc(x int) int {
    return x + 1
}

func sum(x int) int {
    result := 0

    for i := 0; i < x; i++ {
        result += i
    }

    return result
}

func main() {
    n := 666

    fmt.Println(cmb(inc, sum)(n))
    fmt.Println(n * (n + 1) / 2)
}

output:

222111
222111

The related section from the specification: Function types.

All other answers here first declare a new type, which is good (practice) and makes your code easier to read, but know that this is not a requirement.

You can work with function values without declaring a new type for them, as seen in the below example.

Declaring a variable of function type which has 2 parameters of type float64 and has one return value of type float64 looks like this:

// Create a var of the mentioned function type:
var f func(float64, float64) float64

Let's write a function which returns an adder function. This adder function should take 2 parameters of type float64 and should returns the sum of those 2 numbers when called:

func CreateAdder() func(float64, float64) float64 {
    return func(x, y float64) float64 {
        return x + y
    }
}

Let's write a function which has 3 parameters, first 2 being of type float64, and the 3rd being a function value, a function that takes 2 input parameters of type float64 and produces a value of float64 type. And the function we're writing will call the function value that is passed to it as parameter, and using the first 2 float64 values as arguments for the function value, and returns the result that the passed function value returns:

func Execute(a, b float64, op func(float64, float64) float64) float64 {
    return op(a, b)
}

Let's see our previous examples in action:

var adder func(float64, float64) float64 = CreateAdder()
result := Execute(1.5, 2.5, adder)
fmt.Println(result) // Prints 4

Note that of course you can use the Short variable declaration when creating adder:

adder := CreateAdder() // adder is of type: func(float64, float64) float64

Try these examples on the Go Playground.

Using an existing function

Of course if you already have a function declared in a package with the same function type, you can use that too.

For example the math.Mod() has the same function type:

func Mod(x, y float64) float64

So you can pass this value to our Execute() function:

fmt.Println(Execute(12, 10, math.Mod)) // Prints 2

Prints 2 because 12 mod 10 = 2. Note that the name of an existing function acts as a function value.

Try it on the Go Playground.

Note:

Note that the parameter names are not part of the type, the type of 2 functions having the same parameter and result types is identical regardless of the names of the parameters. But know that within a list of parameters or results, the names must either all be present or all be absent.

So for example you can also write:

func CreateAdder() func(P float64, Q float64) float64 {
    return func(x, y float64) float64 {
        return x + y
    }
}

Or:

var adder func(x1, x2 float64) float64 = CreateAdder()

While you can use a var or declare a type, you don't need to. You can do this quite simply:

package main

import "fmt"

var count int

func increment(i int) int {
    return i + 1
}

func decrement(i int) int {
    return i - 1
}

func execute(f func(int) int) int {
    return f(count)
}

func main() {
    count = 2
    count = execute(increment)
    fmt.Println(count)
    count = execute(decrement)
    fmt.Println(count)
}

//The output is:
3
2