Каковы последствия ассоциативности справа налево и слева направо в языках на основе Си? - PullRequest
9 голосов
/ 30 января 2012

Я нахожусь в процессе написания скриптового языка и хочу скопировать (довольно хорошо стандартизированный) порядок операций C.

Одна вещь, которую я никогда не понимал как формальное понятие, это ассоциативность. Почему некоторые группы операторов слева направо, а другие справа налево?

Может ли кто-нибудь дать мне несколько примеров того, как строка кода может выглядеть иначе, если бы все правила были слева направо или противоположно тому, чем они были? Или почему ассоциативность такая, какая она есть, так как она кажется мне произвольным выбором, но я предполагаю, что у них была причина для этого.

Кроме того, просто чтобы заметить, я знаю, что означает ассоциативность, я просто не могу вспомнить ни одного примера, где слева направо (или наоборот) лучше, чем другой выбор

Ответы [ 4 ]

13 голосов
/ 30 января 2012

По большей части каждый оператор имеет ассоциативность, которая наиболее подходит для этого оператора.

Все бинарные операторы без присваивания имеют ассоциативность слева направо.Это полезно по очевидной причине, что английский читается слева направо, и поэтому оценка x + y + z согласуется с тем, как он читается.Кроме того, для арифметических операторов семантика соответствует тому, что мы ожидаем от использования операторов в математике.

Операторы присваивания имеют ассоциативность справа налево.Слева направо назначение будет иметь странную и неожиданную семантику.Например, x = y = z приведет к тому, что x будет иметь исходное значение y, а y будет иметь исходное значение z.Ожидается, что все три переменные будут иметь одно и то же значение после завершения выражения.

Префиксные унарные операторы имеют ассоциативность справа налево, что имеет смысл, поскольку операторы, наиболее близкие к операнду, вычисляются первыми,поэтому в ~!x сначала вычисляется !x, затем к результату применяется ~.Было бы действительно, действительно странно, если бы префиксные операторы применялись с ассоциативностью слева направо: сказать, что ~!x означает оценку ~x, а затем применить ! к результату, является полной противоположностьюкак мы думаем о выражениях (или, по крайней мере, как большинство людей думают о выражениях ...).

6 голосов
/ 30 января 2012

Примеры:

5 - 4 - 3
(5 - 4) - 3 = -2 // left association is correct
5 - (4 - 3) = 4  // right is incorrect

a == b == c // What does this equal?
            // It is common to have == be non-associative because of this.

x = y = z
x = (y = z) // right association is correct, sets x and y
(x = y) = z // left is incorrect, does not set y

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

Унарный ассоциативен справа, потому что он группирует таким образом:

~!-x = ~(!(-(x))) 

Другой способ не имеет особого смысла, если не использовать постфикс.

2 голосов
/ 30 января 2012

Хитрый оператор - возведение в степень (например: ** в python, ^ в R, haskell). Большинство языков, анализаторов и т. Д. Рассматривают 3 ** 3 ** 3 как 3 ** (3 ** 3). Я лично думаю, что это правильная интерпретация, но недавно заметил, что и октава, и matlab вычисляют это как (3 ** 3) ** 3.

Это не проблема в C, так как у него нет оператора возведения в степень. Вместо этого вы вызываете функцию pow и должны явно указать либо pow(3,pow(3,3)), либо pow(pow(3,3),3).

0 голосов
/ 30 января 2012

Накопленное округление обычно является ответом.

Однако >> и << должны быть такими, какие они есть, или конструкции типа 12 << 2 >> 3 не работают.

...