I'm confused on the concept of multiple assignment. Given the following code:
func fibonacci() func() int {
current, next := 0, 1
return func() int {
current, next = next, current+next
return current
}
}
How is the assignment evaluated, given the fact that both variables appear on both the left and right side of the assignment?
The Go Programming Language Specification
Assignments
The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.
The usual example to illustrate multiple assignments is a swap. For example,
package main
import "fmt"
func main() {
{
i, j := 7, 42
fmt.Println(i, j)
// swap i and j - implicit temporaries
i, j = j, i
fmt.Println(i, j)
}
fmt.Println()
{
i, j := 7, 42
fmt.Println(i, j)
// swap i and j - explicit temporaries
ti, tj := i, j
i, j = tj, ti
fmt.Println(i, j)
}
}
Playground: https://play.golang.org/p/HcD9zq_7tqQ
Output:
7 42
42 7
7 42
42 7
The one statement multiple assignment, which uses implicit temporary variables, is equivalent to (a shorthand for) the two multiple assignment statements, which use explicit temporary variables.
Your fibonacci example translates, with explicit order and temporary variables, to:
package main
import "fmt"
func fibonacciMultiple() func() int {
current, next := 0, 1
return func() int {
current, next = next, current+next
return current
}
}
func fibonacciSingle() func() int {
current, next := 0, 1
return func() int {
// current, next = next, current+next
// first phase, evaluation, left-to-right
t1 := next
t2 := current + next
// second phase, assignmemt, left-to-right
current = t1
next = t2
return current
}
}
func main() {
m := fibonacciMultiple()
fmt.Println(m(), m(), m(), m(), m(), m())
s := fibonacciSingle()
fmt.Println(s(), s(), s(), s(), s(), s())
}
Playground: https://play.golang.org/p/XFq-0wyNke9
Output:
1 1 2 3 5 8
1 1 2 3 5 8
The order is defined in Order of Evaluation in the language spec.
At package level, initialization dependencies determine the evaluation order of individual initialization expressions in variable declarations. Otherwise, when evaluating the operands of an expression, assignment, or return statement, all function calls, method calls, and communication operations are evaluated in lexical left-to-right order.
Which comes with a good example of complex evaluation order
y[f()], ok = g(h(), i()+x[j()], <-c), k()
the function calls and communication happen in the order f(), h(), i(), j(), <-c, g(), and k(). However, the order of those events compared to the evaluation and indexing of x and the evaluation of y is not specified.
Operands are evaluated left to right. The fact that next
is assigned to after the operands are evaluated is irrelevant.
Then there are the Assignments:
The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.
So the order here is next
then current+next
. The result of next
is assigned to current
, then the result of current+next
is assigned to next
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With