w3schools ternario operadores operador logicos logico comparar cadenas asignacion javascript haskell logical-operators ecmascript-5 associativity

ternario - operadores logicos javascript w3schools



¿Por qué los operadores lógicos en JavaScript se dejan asociativos? (3)

Para cualquier compilador decente, la asociatividad elegida de estos operadores es bastante irrelevante, y el código de salida será el mismo independientemente. Sí, el árbol de análisis es diferente, pero el código emitido no necesita serlo.

En todos los idiomas de la familia C que conozco (a los que también pertenece Javascript), los operadores lógicos se dejan asociativos. Entonces, la pregunta real es: ¿por qué los lenguajes tipo C definen los operadores lógicos como asociativos por la izquierda? Dado que la asociatividad elegida es irrelevante (en términos de semántica y en términos de eficiencia), mi sospecha es que se eligió la asociatividad más "natural" (como en "lo que la mayoría de los otros operadores usan"), aunque no lo hago. No tengo ninguna fuente para respaldar mis afirmaciones. Otra posible explicación es que los operadores asociativos a la izquierda toman menos espacio de pila para analizar utilizando un analizador LALR (lo que no es una gran preocupación en la actualidad, pero probablemente fue cuando C apareció).

Los operadores lógicos AND y OR son los únicos operadores perezosos en JavaScript junto con el operador condicional ternario. Se prueban para la evaluación de cortocircuito usando las siguientes reglas:

false && anything === false true || anything === true

Esta es la misma forma en que se implementa en Haskell:

(&&) :: Bool -> Bool -> Bool False && _ = False True && x = x (||) :: Bool -> Bool -> Bool True || _ = True False || x = x

Sin embargo, de acuerdo con MDN, los operadores lógicos en JavaScript son asociativos . Esto es contrario a la intuición. En mi humilde opinión deberían ser acertados asociativos. Haskell hace lo correcto. Los operadores lógicos en Haskell son asociativos de derecho:

infixr 3 && infixr 2 ||

Considera la siguiente expresión en Haskell:

False && True && True && True

Debido a que && es asociativo en Haskell, la expresión anterior es equivalente a:

False && (True && (True && True))

Por lo tanto, no importa qué evalúa la expresión (True && (True && True)) . Debido al primer False la expresión completa se reduce a False en un solo paso.

Ahora considera qué pasaría si && quedara asociativa. La expresión sería equivalente a:

((False && True) && True) && True

Ahora se necesitarían 3 reducciones para evaluar la expresión completa:

((False && True) && True) && True (False && True) && True False && True False

Como puede ver, tiene más sentido para los operadores lógicos ser asociativos correctos. Esto me lleva a mi pregunta real:

¿Por qué los operadores lógicos en JavaScript se dejan asociativos? ¿Qué tiene que decir la especificación ECMAScript sobre esto? ¿Son los operadores lógicos en JavaScript en verdad asociativos? ¿Los documentos de MDN tienen información incorrecta sobre la asociatividad de los operadores lógicos?

Edición: Según la specification los operadores lógicos se dejan asociativos:

LogicalANDExpression = BitwiseORExpression | LogicalANDExpression && BitwiseORExpression LogicalORExpression = LogicalANDExpression | LogicalORExpression || LogicalANDExpression


Respuesta simple: Imagina var i = nulo; if (i == null || i.getSomeValue ()) ... Cuando no se deja asociativo, la segunda prueba se evaluará primero y le dará una excepción.


Considere este código:

console.log( true || (false && true) ); // right associative (implicit) console.log( (true || false) && true ); // left associative (Javascript)

Ambos ejemplos devuelven el mismo resultado, pero esa no es la razón para preocuparse por la asociatividad del operador. La razón por la que es relevante aquí se debe a la forma única en que los operadores lógicos determinan sus resultados. Aunque todas las permutaciones finalmente llegan a la misma conclusión final, el orden de los cálculos cambia, y eso puede tener grandes implicaciones para su código.

Entonces, ahora considera esto:

var name = ""; // ---------------------------------------- // Right associative // ---------------------------------------- name = "albert einstein"; console.log("RIGHT : %s : %s", true || (false && updateName()), name); // ---------------------------------------- // Left Associative // ---------------------------------------- name = "albert einstein"; console.log("LEFT : %s : %s", (true || false) && updateName(), name); function updateName() { name = "charles manson"; return true; }

La salida es:

RIGHT : true : albert einstein LEFT : true : charles manson

Ambas expresiones devuelven verdadero, pero solo la versión asociada izquierda tuvo que llamar a updateName () para devolver una respuesta. La versión asociada correcta es diferente. Solo evalúa el primer argumento en (false && updateName()) porque el segundo argumento no puede cambiar el false a true .

Recuerda estos dos puntos:

  • La precedencia del operador describe el orden de anidamiento de expresiones compuestas de diferentes tipos de operadores.
  • La asociación de operadores describe el orden de anidamiento de las expresiones compuestas con la misma precedencia de operadores.

Tenga en cuenta que ninguno de los dos puntos anteriores cambia la forma en que se interpreta una expresión individual, solo la forma en que se interpretan las expresiones compuestas . La asociatividad ocurre en un nivel superior.

La asociatividad del operador, así como la precedencia del operador, tienen un enorme impacto en cómo se comporta un lenguaje. Comprender cuáles son esas diferencias es fundamental para poder usar y captar rápidamente las diferencias funcionales en diversos lenguajes de programación. Definitivamente obtienes mi aprobación por tu pregunta y espero que esto aclare un poco las cosas. Cuídate.