2014-10-30 1 views
6

Я пишу функцию Go, которая подражает Python itertools.permutations(), но возвращает все перестановки сразу, а не дает по одному.Golang - Неожиданное поведение с несколькими присваиваниями

Я вижу неожиданное поведение при обновлении 2 переменных в то же время в следующих строках коды:

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:]...) 
} 

я получить правильные результаты при развязке вышеупомянутого обновления:

current[i] = setcopy[c] 
setcopy = append(setcopy[:c], setcopy[c+1:]...) 

I был в основном вдохновлен Pop и Delete примерами статьи wiki SliceTricks. Есть ли существенная разница между тем и тем, что я пытаюсь сделать?

Если вы хотите проверить полный код (включая пример неисправного вывода и некоторые инструкции печати для отладки), вы можете проверить this Gist.

ответ

7

The Go Programming Language Specification

Assignments

Доходы назначения в два этапа. Во-первых, операнды индекса выражений и указателей (включая неявный указатель без указания в селекторах) слева, а выражения в правлении оцениваются в обычном порядке. Во-вторых, задания выполняются в порядке слева направо.

Operands

Операнды обозначают элементарные значения в выражении. Операнд может быть литералом, (возможно, квалифицированным) непустым идентификатором, обозначающим константу, переменную или функцию , выражение метода, дающее функцию или выражение в скобках.

Order of evaluation

При оценке операндов выражения, присвоение или вернуть заявления, все вызовы функций, вызовы методов и коммуникационные операций оцениваются в лексическом порядке слева направо.

Например, в (функции локального) присвоение вызовов

y[f()], ok = g(h(), i()+x[j()], <-c), k() 

функции и коммуникации происходят в порядке F(), ч(), I(), J(), < - c, g() и k(). Однако порядок этих событий по сравнению с оценкой и индексацией x и оценкой y не указан.

Appending to and copying slices

Если емкость с недостаточно большой, чтобы вместить дополнительные значения, Append выделяет новый, достаточно большой основной массив, который соответствует как существующие элементы фрагмента и дополнительные значения. В противном случае, append повторно использует базовый массив.

Рассчитывается ли новый базовый массив?

Оператор присваивания

current[i], setcopy = setcopy[c], append(setcopy[:c], setcopy[c+1:]...) 

оказывается эквивалентным

a := append(setcopy[:c], setcopy[c+1:]...) 
x := setcopy[c] 
y := a 
current[i], setcopy = x, y 

но порядок событий вызова функции по сравнению с оценкой других операндов не указан (Order of evaluation).

+0

Я так не думаю, так как 'append', используемый в присваивании, фактически уменьшает размер фрагмента/удаления элемента (и как таковой новый массив не понадобится). – Redy

+1

Не могу объяснить, почему, но результат такой же, как если бы 'append' запускался первым: http://play.golang.org/p/ZQ-4cMyNTJ – twotwotwo

+0

Кажется, что вы обещали, правильный порядок eval - если никто не придумает здесь вескую причину, я бы ударил golang-nuts этим, кажется действительно странным. – twotwotwo

Смежные вопросы