2012-01-30 13 views
9

estoy en el proceso de escritura de un lenguaje de script y quiero copiar la (bastante bien estandarizada) C order of operations.¿Cuáles son las ramificaciones de la asociatividad de derecha a izquierda y de izquierda a derecha en los lenguajes basados ​​en C?

Una cosa que nunca he tenido una firme comprensión de como un concepto formal es sin embargo la asociatividad. ¿Por qué algunos grupos de operadores son de izquierda a derecha y otros de derecha a izquierda?

¿Puede alguien darme algunos ejemplos de cómo una línea de código podría verse diferente si las reglas fueran todas de izquierda a derecha o lo contrario de lo que eran? O por qué la asociatividad es la forma en que es, ya que me parece una elección arbitraria, pero supongo que tenían una razón para ello.

Además, sólo tener en cuenta, lo que sí sé lo que significa la asociatividad, que no puedo pensar en ninguna ejemplos en los que de izquierda a derecha (o viceversa) es mejor que la otra opción

+0

¡Es una pregunta genial! También vea [why-does-the-assignment-operator-assign-to-the-left-hand-side] (http://programmers.stackexchange.com/questions/98406/why-does-the- assignment-operator- assign-to-the-left-hand-side) – nawfal

Respuesta

13

En su mayor parte, cada operador tiene la asociatividad que tiene más sentido para ese operador.

Todos los operadores binarios sin asignación tienen asociatividad de izquierda a derecha. Esto es útil por la razón obvia de que el inglés se lee de izquierda a derecha y, por lo tanto, la evaluación de x + y + z es consistente con la forma en que se lee. Además, para operadores aritméticos, la semántica coincide con lo que esperamos del uso de los operadores en matemáticas.

Los operadores de asignación tienen asociatividad de derecha a izquierda. La asignación de izquierda a derecha tendría una semántica extraña e inesperada. Por ejemplo, x = y = z daría como resultado x teniendo el valor original de y y y teniendo el valor original de z. Se espera que las tres variables tengan el mismo valor después de que se complete la expresión.

El prefijo operadores unarios tienen asociatividad de derecha a izquierda, que tiene sentido debido a que los operadores más cercanos al operando se evalúan primero, por lo que en ~!x, !x se evalúa primero, entonces ~ se aplica al resultado.Sería realmente, realmente extraños fueron los operadores de prefijos aplicados con asociatividad de izquierda a derecha: decir que ~!x significa evaluar ~x y luego aplicar ! al resultado es todo lo contrario de cómo pensamos sobre las expresiones (o, al menos, , cómo la mayoría de la gente piensa en expresiones ...).

+1

En C, la asociatividad de izquierda a derecha de los operadores de asignación haría 'x = y = z' un error (por la misma razón que' (x = y) = z' es un error). – caf

+0

@caf: cierto, pero si uno está considerando cambiar la asociatividad de un operador, también podría considerar cambiar la categoría de valor de la expresión del operador. –

0

acumulada de redondeo usualmente es la respuesta.

Sin embargo, >> y < < tienen que ser como están o las construcciones como 12 < < 2 >> 3 no funcionan.

6

Ejemplos:

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 

mayoría de los operadores heredan su asociatividad de las matemáticas. Bitwise puede verse como operadores aritméticos y, por lo tanto, tienen asociatividad izquierda.

Unario es asociativa correcto porque los grupos de esa manera:

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

La otra forma no tendría mucho sentido a menos de sufijo.

+1

No me gusta la no asociatividad. En mi opinión, 'a == b == c' debe significar' (a == b) == c' (compare el resultado booleano de 'a == b' a' c') o debe tener una cubierta especial como en Python para 'let b '= b in (a == b') && (b '== c)'. –

2

El operador complicado es exponenciación (por ejemplo: ** en python,^en R, haskell). La mayoría de los lenguajes, analizadores sintácticos, etc. ver 3 ** 3 ** 3 como 3 ** (3 ** 3). Personalmente creo que esta es la interpretación correcta, pero recientemente noté que tanto la octava como el matlab calculan esto como (3 ** 3) ** 3.

Esto no es un problema en C ya que no tiene un operador de exponenciación. En su lugar, realiza llamadas a la función pow y tiene que indicar explícitamente pow(3,pow(3,3)) o pow(pow(3,3),3).

+2

También es correcto asociativo en Cobol, y en Fortran: http://www.fortran.com/F77_std/rjcnf0001-sh-6.html. Matemáticamente hablando, esta es la interpretación correcta. – EJP

Cuestiones relacionadas