Articulo de referencia

Asociatividad de operadores

En la teoría de los lenguajes de programación , la asociatividad de un operador es una propiedad que determina cómo se agrupan los operadores de la misma precedencia en ausencia...

En la teoría de los lenguajes de programación , la asociatividad de un operador es una propiedad que determina cómo se agrupan los operadores de la misma precedencia en ausencia de paréntesis . Si un operando está precedido y seguido por operadores (por ejemplo, ^ 3 ^), y estos operadores tienen la misma precedencia, entonces el operando puede usarse como entrada para dos operaciones diferentes (es decir, las dos operaciones indicadas por los dos operadores). La elección de a qué operaciones aplicar el operando viene determinada por la asociatividad de los operadores. Los operadores pueden ser asociativos (lo que significa que las operaciones pueden agruparse arbitrariamente), asociativos por la izquierda (lo que significa que las operaciones se agrupan desde la izquierda), asociativos por la derecha (lo que significa que las operaciones se agrupan desde la derecha) o no asociativos (lo que significa que las operaciones no pueden encadenarse, a menudo porque el tipo de salida es incompatible con los tipos de entrada). La asociatividad y la precedencia de un operador forman parte de la definición del lenguaje de programación; diferentes lenguajes de programación pueden tener diferente asociatividad y precedencia para el mismo tipo de operador.

Consideremos la expresión a ~ b ~ c. Si el operador ~tiene asociatividad izquierda, esta expresión se interpretaría como (a ~ b) ~ c. Si el operador tiene asociatividad derecha, la expresión se interpretaría como a ~ (b ~ c). Si el operador no es asociativo, la expresión podría ser un error de sintaxis o podría tener algún significado especial. Algunos operadores matemáticos tienen asociatividad inherente. Por ejemplo, la resta y la división, tal como se usan en la notación matemática convencional, son inherentemente asociativas izquierdas. La suma y la multiplicación, por el contrario, son asociativas tanto izquierdas como derechas. (p. ej. (a * b) * c = a * (b * c)).

Muchos manuales de lenguajes de programación proporcionan una tabla de precedencia y asociatividad de operadores; véase, por ejemplo, la tabla para C y C++ .

El concepto de asociatividad notacional que se describe aquí está relacionado con la asociatividad matemática, pero es diferente . Una operación matemáticamente asociativa, por definición, no requiere asociatividad notacional. (Por ejemplo, la suma posee la propiedad asociativa, por lo que no tiene por qué ser asociativa por la izquierda ni por la derecha). Sin embargo, una operación que no es matemáticamente asociativa debe ser asociativa por la izquierda, por la derecha o no asociativa en la notación. (Por ejemplo, la resta no posee la propiedad asociativa, por lo que debe tener asociatividad notacional).

Ejemplos

La asociatividad solo es necesaria cuando los operadores de una expresión tienen la misma precedencia. Normalmente, +y -tienen la misma precedencia. Consideremos la expresión 7 - 4 + 2. El resultado podría ser (7 - 4) + 2 = 5o 7 - (4 + 2) = 1. El primer resultado corresponde al caso en que +y -son asociativos por la izquierda, el segundo al caso en que +y -son asociativos por la derecha.

Para reflejar el uso normal, los operadores de suma , resta , multiplicación y división suelen ser asociativos por la izquierda, [ 1 ] [ 2 ] [ 3 ] mientras que para un operador de exponenciación (si está presente) [ 4 ] no hay un acuerdo general. Cualquier operador de asignación suele ser asociativo por la derecha. Para evitar casos en los que los operandos se asocien con dos operadores, o con ningún operador, los operadores con la misma precedencia deben tener la misma asociatividad.

Un ejemplo detallado

Consideremos la expresión 5^4^3^2, en la que ^se toma como un operador de exponenciación asociativo por la derecha. Un analizador sintáctico que lea los tokens de izquierda a derecha aplicaría la regla de asociatividad a una rama, debido a la asociatividad por la derecha de ^, de la siguiente manera:

  1. El término 5está leído.
  2. Se lee un no terminal ^. Nodo: " 5^".
  3. El término 4se lee. Nodo: " 5^4".
  4. Se lee el no terminal ^, lo que activa la regla de asociatividad derecha. La asociatividad decide el nodo: " 5^(4^".
  5. El término 3se lee. Nodo: " 5^(4^3".
  6. Se lee un no terminal ^, lo que activa la reaplicación de la regla de asociatividad derecha. Nodo " 5^(4^(3^".
  7. El término 2se lee. Nodo " 5^(4^(3^2".
  8. No hay tokens para leer. Aplicar la asociatividad para producir el árbol de análisis sintáctico " 5^(4^(3^2))".

Esto se puede evaluar luego en profundidad, comenzando por el nodo superior (el primero ^):

  1. El evaluador recorre el árbol, desde la primera ^expresión, pasando por la segunda, hasta la tercera.
  2. Se evalúa como: 3 2 = 9. El resultado reemplaza la rama de expresión como el segundo operando del segundo ^.
  3. La evaluación continúa un nivel más arriba en el árbol de análisis como: 4 9 = 262,144 . Nuevamente, el resultado reemplaza la rama de expresión como el segundo operando del primero ^.
  4. Nuevamente, el evaluador sube por el árbol hasta la expresión raíz y evalúa como: 5 2621446,206 0699 × 10 183 230 . La última rama restante colapsa y el resultado se convierte en el resultado general, completando así la evaluación general.

Una evaluación asociativa izquierda habría dado como resultado el árbol de análisis ((5^4)^3)^2y el resultado completamente diferente (625 3 ) 2 = 244,140,625 25.960 4645 × 10 16 .

Asociatividad derecha de los operadores de asignación

En muchos lenguajes de programación imperativos , el operador de asignación se define como asociativo por la derecha, y la asignación se define como una expresión (que se evalúa a un valor), no solo como una instrucción. Esto permite la asignación encadenada utilizando el valor de una expresión de asignación como operando derecho de la siguiente.

En C , la asignación a = bes una expresión que se evalúa al mismo valor que la expresión bconvertida al tipo de a, con el efecto secundario de almacenar el valor R de ben el valor L de a. [ a ] ​​Por lo tanto, la expresión a = (b = c)puede interpretarse como b = c; a = b;. La expresión alternativa (a = b) = cgenera un error porque a = bno es una expresión de valor L, es decir, tiene un valor R pero no un valor L donde almacenar el valor R de c. La asociatividad derecha del =operador permite que expresiones como a = b = cse interpreten como a = (b = c).

En C++ , la asignación a = bes una expresión que se evalúa al mismo valor que la expresión a, con el efecto secundario de almacenar el valor R de ben el valor L de a. Por lo tanto, la expresión a = (b = c)aún puede interpretarse como b = c; a = b;. Y la expresión alternativa (a = b) = cpuede interpretarse como a = b; a = c;en lugar de generar un error. La asociatividad derecha del =operador permite que expresiones como a = b = cse interpreten como a = (b = c).

Operadores no asociativos

Los operadores no asociativos son aquellos que no tienen un comportamiento definido cuando se usan en secuencia en una expresión. En Prolog, el operador infijo no :-es asociativo porque construcciones como " " constituyen errores de sintaxis.a :- b :- c

Otra posibilidad es que las secuencias de ciertos operadores se interpreten de otra manera, que no puede expresarse como asociatividad. Esto generalmente significa que, sintácticamente, existe una regla especial para las secuencias de estas operaciones, y semánticamente el comportamiento es diferente. Un buen ejemplo es Python , que tiene varias construcciones de este tipo. [ 5 ] Dado que las asignaciones son sentencias, no operaciones, el operador de asignación no tiene un valor y no es asociativo. La asignación encadenada se implementa mediante una regla gramatical para secuencias de asignaciones a = b = c, que luego se asignan de izquierda a derecha. Además, las combinaciones de asignación y asignación aumentada , como a = b += cno son válidas en Python, aunque sí lo son en C. Otro ejemplo son los operadores de comparación, como >, ==, y <=. Una comparación encadenada como se interpreta como , no equivalente a o . [ 6 ]a < b < c(a < b) and (b < c)(a < b) < ca < (b < c)

Véase también

Notas

  1. Una expresión puede convertirse en una proposición siguiéndola con un punto y coma; es decir,a = bes una expresión, peroa = b;es una proposición.

Referencias

  1. Lugar de la educación: El orden de las operaciones
  2. Khan Academy : El orden de las operaciones , minuto 5:40
  3. Departamento de Educación de Virginia: Uso del orden de operaciones y exploración de propiedades. Archivado el 16 de julio de 2022 en Wayback Machine , sección 9.
  4. Exponenciación, asociatividad y notación matemática estándar Codeplea. 23 de agosto de 2016. Consultado el 20 de septiembre de 2016.
  5. Referencia del lenguaje Python , " 6. Expresiones "
  6. Referencia del lenguaje Python , " 6. Expresiones ": 6.9. Comparaciones