I'm writing a Go function that kind of mimics Python's itertools.permutations()
, but returning all permutations at once instead of yielding one at a time.
I'm seeing unexpected behavior when updating 2 variables at the same time in the following lines of code:
setcopy := append([]int(nil), sorted...)
for i := 0; i < r; i++ {
c := counters[r-1-i]
current[i], setcopy = setcopy[c], append(setcopy[:c], setcopy[c+1:]...)
}
I get correct results when decoupling the above update:
current[i] = setcopy[c]
setcopy = append(setcopy[:c], setcopy[c+1:]...)
I was mainly inspired by the Pop
and Delete
examples from the SliceTricks wiki article. Is there a significant difference between that and what I'm trying to do?
If you'd like to check out the full code (including an example of the faulty output and some print statements for debugging), you can check out this Gist.
The Go Programming Language Specification
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.
Operands denote the elementary values in an expression. An operand may be a literal, a (possibly qualified) non-blank identifier denoting a constant, variable, or function, a method expression yielding a function, or a parenthesized expression.
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.
For example, in the (function-local) assignment
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.
Appending to and copying slices
If the capacity of s is not large enough to fit the additional values, append allocates a new, sufficiently large underlying array that fits both the existing slice elements and the additional values. Otherwise, append re-uses the underlying array.
Is a new underlying array is being allocated?
The assignment statement
current[i], setcopy = setcopy[c], append(setcopy[:c], setcopy[c+1:]...)
appears to be equivalent to
a := append(setcopy[:c], setcopy[c+1:]...)
x := setcopy[c]
y := a
current[i], setcopy = x, y
but the order of function call events compared to evaluation of other operands is not specified (Order of evaluation).