Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go: Anonymous Function

Tags:

go

Here is the code I've been trying to understand:

package main

import (
    "fmt"
)

func squares() func() int {
    var x int
    return func() int {
        x = x + 2
        return x * x
    }
}

func main() {
    f := squares()
    fmt.Println(f())
    fmt.Println(f())
    fmt.Println(f())
    fmt.Println(squares()())
    fmt.Println(squares()())
    fmt.Println(squares()())
}

The result we got:

4
16
36
4
4
4

My question is: Why does the value of x in fmt.Println(squares()()) stay unchanged?

like image 421
Pauli Avatar asked Jul 27 '26 01:07

Pauli


1 Answers

Short version

You are building a new closure each time you call squares.

This is exactly as if you built a new Counter object in an object-oriented language:

new Counter().increment(); // 4
new Counter().increment(); // 4

...as opposed to:

c = new Counter();
c.increment(); // 4
c.increment(); // 16

Longer version

In your function, var x int declares a local variable x:

func squares() func() int {
    var x int
    return func() int {
        x = x + 2
        return x * x
    }
}

As for any function, local variables are visible only inside the function. If you call a function in different contexts, each call has a separate set of memory storage addressable by your local symbols (here x). What happens when you return a function is that any binding currently visible in the scope of your code is kept alongside your function, which is then called a closure.

Closures can hold a state, like objects do. Thus your closure can refer to the local variables that were visible when it was created, even when you escape the block where local variables were introduced (thankfully, the GC is here to keep track of the memory associated with those variables).

When you define f, you create a fresh closure. Each time you call it you modify the same place referenced by the internal x variable. But if you create fresh closures and call them once each, then you won't see the same side-effects, because each x names a different place in memory.

like image 197
coredump Avatar answered Jul 29 '26 21:07

coredump



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!