Go: Anonymous Function - 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?

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.

The reason you are getting the same result when you are calling the second variant with closure function is a consequence of scope rules. All function values created by the new self invoking, or anonymous function, capture and share the same variable - an addressable storage location, not it's value at that particular moment.
The anonymous function introduce a new lexical block which shares the same logical address to which the function values points to, so each time you invoke the function without to enclose the function to a new scope it will share the same logical address. This is the reason why you'll see in many places an anonymous function called in this way:
for i := range mymap {
func(n int) {
fmt. Println(n)
}(i) // note the scope
}
To address your issue one way would be to use pointer variables, this way you will be absolute sure that you will share the variable allocated to the same memory address. Here is the updated and working code:
package main
import (
"fmt"
)
func squares() func(x *int) int {
return func(x *int) int {
*x = *x + 2
return *x * *x
}
}
func main() {
f := squares()
x := 0
fmt.Println(f(&x))
fmt.Println(f(&x))
fmt.Println(f(&x))
fmt.Println(squares()(&x))
fmt.Println(squares()(&x))
fmt.Println(squares()(&x))
}
Go Playground
Another way is to expose the variable x as a global variable. This will guarantee that you won't create a new variable x each time you run the anonymous function.

Here's a different perspective to answer your question.
First break down the squares() function first to understand what is going on:
func squares() func() int {
The above defines a func named squares that returns another function of type func() int (and that returns an int, but that's not the focus here).
Drill that into your head first: it returns a function.
Now, let's see what happens when we call squares():
var x int
That's it. It defines a varibale x, which defaults to value 0 per Go specs.
OK, now we have a variable in scope called x and it has a value of 0. Now, we return a function:
return func() int {
x = x + 2
return x * x
}
If we had not defined x earlier, this would be a build error because x must be defined. But, it was defined in the previous scope.
Go's use of closures allows another scope to be defined, which uses variables in the previous scope. var x int in this case.
Also, you are able to modify closures (variables in previous scope). And in this case, we are modifying the previous var x int that was defined in the previous scope.
Hold onto those thoughts for a moment, let's run some code...
f := squares()
Here we run squares(), which defines var x int as zero and returns a func() named f() that can do more work on x.
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
Since we continue to reuse f(), this keeps the scope of var x int on a stack, and that stack remains around as long as you have this f() variable. Therefore, x continues to retain its modified value and be modified.
With all of this knowledge, the answer to your question is simple: if you don't retain the scope, the f() definition like above, then you define a new var x int = 0 at every invitation of squares():
fmt.Println(squares()())
This invokes a new squares() at every call. And therefore, a new var x int = 0.
So the output of the returning func of squares, which is invoked with squares()(), always operates on var x int = 0, at every invokation since a new squares is called each time.

Simply because (1) x is a captured closure for the anonymous function and (2) the default value for type int is 0. So every time you call it, you will see the same output.
Let's rewrite the function squares like this:
func squares(initialValue int) func() int {
var x int
x = initialValue
return func() int {
x = x + 2
return x * x
}
}
Now for this:
func main() {
f := squares(0)
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println(squares(0)())
fmt.Println(squares(0)())
fmt.Println(squares(0)())
}
We will see the exact output! Because we are initializing x with 0. If we use 1 as the initial value of x:
func main() {
f := squares(1)
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println(squares(1)())
fmt.Println(squares(1)())
fmt.Println(squares(1)())
}
We will see this result:
9
25
49
9
9
9
As you can see, it's just about the initial value of x, which when not initialized explicitly, will have it's default value, zero.

Related

Do slices or arrays act as a global scope?

I'm still new to programming. Forgive my lack of computer science knowledge. Not sure if this question is specific to Golang or computer science in general...
I always thought that functions do not alter variables/data held outside their own scope unless you use a return statement back into the other scope, or unless they are higher in the hierarchy of scopes. One may argue that functions f1 and f2 in this example are called from a lower scope. However, this still doesn't explain why I'm getting different results for variable num and nums.
package main
import "fmt"
func f1(a int) {
a = 50 // this will not work, as it shouldn't
}
func f2(a ...int) {
a[0] = 50 // this will work without return statement
a[1] = 50 // this will work without return statement
}
func main() {
num := 2
nums := []int{2, 2}
f1(num)
f2(nums...)
fmt.Printf("function f1 doesn't affect the variable num and stays: %v\n", num)
fmt.Printf("function f2 affects the variable nums and results in: %v", nums)
Questions:
Why doesn't f2 require a return statement to modify nums like num
would within f1?
Golang functions are said to pass values (rather than reference),
shouldn't that force the function to return copies?
Can this happen in other languages? (I think I may have
seen this in other languages).
This is the correct behaviour, since a ...int is equal to a slice e.g.: a []int
func f2(a []int) {
a[0] = 50
a[1] = 50
}
func main() {
b := []int{2, 2}
f2(b)
fmt.Println(b) // [50 50]
}
And a slice is a view to the original data, here 'b'.
"Why doesn't f2 require a return statement to modify nums like num would in f1?"
In f2 you are using the slice, which has a pointer to the original array, so f2 can change the outside array.
"Golang functions are said to pass values (not reference), shouldn't that force to return copies? (If the question is related...)"
In f2 the slice itself is passed by value, meaning pointer and length and capacity of the original array.
"Can this happen in other languages? (I think I may have seen this in other langues)"
Too broad to answer, there are many languages and in general if you have a pointer to the outside world array, yes.
Edit:
package main
import "fmt"
func sum(a ...int) int {
s := 0
for _, v := range a {
s += v
}
return s
}
func f2(a []int) {
c := make([]int, len(a))
copy(c, a)
c[0] = 50
fmt.Println(sum(c...)) // 52
}
func main() {
b := []int{2, 2}
fmt.Println(sum(1, 2, 3, 4)) // 10
fmt.Println(sum(b...)) // 4
f2(b)
fmt.Println(b) // [2 2]
}
Notes:
The sum() function above is a pure function, since it has no side effect.
The new f2 function above is a pure function, since it has no side effect: it makes a copy of a into c then calls the sum.
In go, function arguments are passed by value. That means, if you pass an int (like in f1), compiler will pass the value of f1, essentially copying it. If the function takes a *int and you pass &num, then the compiler passes the value of &num, which is a pointer to num. When the function changes *num, the value of the variable outside the function will change. If the function changes num, the pointer value of num will change, and it will point to a different variable.
As a contrast, Java passes all primitive values as value, and all objects by reference. That is, if you pass an int, there is no way for the function to modify the value of that int that is visible to the caller. If you want to pass an int the function can modify, you put that in a class and pass an instance of that class in Java.
A slice (as in f2) contains a pointer to the underlying array. When you call a function with a slice, the slice header (containing a pointer to the underlying array) is copied, so when the function changes the slice elements, the underlying array elements change.
The question of scope is somewhat different. Scope of a function is all the variables it can see. Those are the global variables (if from different packages, exported global variables), function arguments, and if the function is declared nested within another function, all the variables visible in that function at that point.
1 & 2) Both questions can be answered when looking at how slices work in Go. There's a blog article on it.
In general, all variables are passed by value in Go. You can use pointers (e.g. *int for f1) to pass by reference (or more correct, the address of the pointer).
However, slices are technically also passed by value.
When we look here, we can get an idea how they work:
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
Len and Cap are integers, but Data is a pointer.
When this struct is copied (when passing by value), a copy of Len, Cap and Data will be made. Since Data is a pointer, any modifications made to the value it's pointing to will be visible after your function returns.
You can also read this

Why doesn't Scanf() work correctly for me?

I'm trying to move from Python to GO and with my minimal knowledge I tried to make a basic calculator. However i for some reason can't get Scanf to work properly. It only seems to accept the first scanf but the second one is completely ignored
package main
import (
"fmt"
)
var x int
var y int
var result int
var input float64
func add(x int, y int) int {
sum := x + y
return sum
}
func sub(x int, y int) int {
sum := x - y
return sum
}
func div(x int, y int) int {
sum := x / y
return sum
}
func mul(x int, y int) int {
sum := x * y
return sum
}
func main() {
fmt.Println("Which type?\n1: Add\n2: Subtract\n3: Divide\n4:
Multiply")
fmt.Scanf("%d", &input)
fmt.Println("Input numbers seperated by space")
fmt.Scanf("%d", x, y)
switch input {
case 1:
result = add(x, y)
case 2:
result = sub(x, y)
case 3:
result = div(x, y)
case 4:
result = mul(x, y)
}
fmt.Println(result)
}
The second call to Scanf, Scanf("%d", x, y) only provides one conversion specifier but was given two variables.
Moreover, this second call only passes the variables' values, not their addresses.
It seems the correct call would be Scanf("%d %d", &x, &y)
In the first call to Scanf you said: Scanf("%d", &input). The second argument's syntax, & variable, denotes a reference to the named variable.
input was declared global, but is only visible after its declaration. Since input is in scope within main but not within Scanf, in order for Scanf to change the value in another scope, the address must be given as an argument, rather than its value.
The recipient of the address (here Scanf) can then change the value of the variable in the frame in which it is still in scope; in this case, main.
See Go's documentation for a similar explanation: https://golang.org/ref/spec#Address_operators

Why are variables in closure not forgotten?

The following code:
package main
import "fmt"
// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
first, second := 0, 1
return func() int {
// return next fibonacci number here.
first, second = second, first+second
return first
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
returns 10 numbers of the fibonacci sequence. What's confusing to me is why is works. It seems like the values first and second are somehow saved in memory, since each time the code is executed, a new fibonacci number in sequence with the previous one is returned. I thought that functions lost their remembered variables when they were done executing. What is going on here?
first, and second are variables in the fibonacci() func, that were 'closed over' by the returned func() int that was returned from fibonacci().
So they are in the closure associated with f, so f has access to those variables as long as it exists.
See this Go Tour slide (and the ones around it) for some explanation of Go closures.

Access one of the multiple result parameters return by a function in go

Here's the sample code (from tour.golang.org),
package main
import "fmt"
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
func main() {
x, _ := split(17)
fmt.Println(x)
}
I would like to know if it is possible to shorten the main function to just a single line. Logically there should be a way (might not look very elegant in this case though) to access only first result parameter returned from function and print it.
fmt.Println is a variadic function, so you can just pass the split function as a parameter:
func main() {
fmt.Println(split(17))
}
see it working in full here: http://play.golang.org/p/c1zkFVMe11

Different behavior between calling function directly and using pointer

I am new to Go language and got confused with the following code
package main
import "fmt"
// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
previous := 0
current := 1
return func () int{
current = current+previous
previous = current-previous
return current
}
}
func main() {
f := fibonacci
for i := 0; i < 10; i++ {
fmt.Println(f()())
}
}
This code is supposed to print out the Fibonacci Sequence (first 10), but only print out 10 times 1.
but if I change the code to:
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
Then it is working fine. The output is the Fibonacci sequence.
Could any one help me explain this?
Thanks
fibonacci() creates a new fibonacci generator function. fibonacci()() does the same, and then calls it once, returns the result and discards the generator, never to be used again. If you call that in a loop, it'll just keep creating new generators and only using their first value.
If you want more than just the first value, you need to do exactly what you did in your second example. Store the generator itself in a variable and then call the same generator multiple times.
This has to do with how variables are encapsulated in closures after returning the closure.
Consider the following example (live code on play):
func newClosure() func() {
i := 0
fmt.Println("newClosure with &i=", &i)
return func() {
fmt.Println(i, &i)
i++
}
}
func main() {
a := newClosure()
a()
a()
a()
b := newClosure()
b()
a()
}
Running this code will yield something like the following output. I annotated
which line comes from which statement:
newClosure with &i= 0xc010000000 // a := newClosure()
0 0xc010000000 // a()
1 0xc010000000 // a()
2 0xc010000000 // a()
newClosure with &i= 0xc010000008 // b := newClosure()
0 0xc010000008 // b()
3 0xc010000000 // a()
In the example, the closure returned by newClosure encapsulates the local variable i.
This corresponds to current and the like in your code. You can see that a and b
have different instances of i, or else the call b() would've printed 3 instead.
You can also see that the i variables have different addresses. (The variable is already
on the heap as go does not have a separate stack memory, so using it in the closure is
no problem at all.)
So, by generating a new closure you're automatically creating a new context for the
closure and the local variables are not shared between the closures. This is the reason
why creating a new closure in the loop does not get you further.
The equivalent in for your code in terms of this example would be:
for i:=0; i < 10; i++ {
newClosure()()
}
And you've already seen by the output that this will not work.
func fibonacci() func() int return a function literal (closure) that returns an int representing the last generated number in the list.
The first main() method
f := fibonacci
for i := 0; i < 10; i++ {
fmt.Println(f()())
}
f is the generator function, every iteration in the loop invoke f()() that generates a new closure with a new envirement ( previous := 0, current := 1), so , the second invocation returns current which is always equal to 1.
The second main() method
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
f is the closure (not the generator) with an initial envirement ( previous := 0, current := 1), every iteration in the loop invoke f() witch returns current and modify the envirement, so whith the next call, previous will be 1 and current 2.

Resources