¿Por qué no hay operadores de asignación compuesta para operadores lógicos (como ||, &&, etc.)?

20

De acuerdo con ECMA-262, parte 11.13, siguiente es la lista exhaustiva de operadores de asignación compuestos: *= /= %= += -= <<= >>= >>>= &= ^= |=.

De acuerdo con la parte 11.11, var c = a || bpondrá avalor en csi ToBoolean(a)es verdadero y pondrá bvalor en ccaso contrario. Como tal, el OR lógico se usa a menudo como el operador de fusión, por ejemplo

function (options) {
    options = options || {};
}

Con suficiente frecuencia, se unen se utiliza para especificar el valor predeterminado para la variable, como se ha mostrado arriba a = a || b.

Parece que el operador de asignación compuesta ||=sería muy útil, que permite escribir el código anterior de una forma más corta y más limpio: a ||= b. Sin embargo, no está allí (aunque *=, +=y otros operadores de asignación compuestos son).

La pregunta es, ¿por qué?

penartur
fuente
2
Estoy increíblemente perplejo de que el operador% = incluso exista. ¿Quién decidió que era necesario? Algunos de estos operadores parecen malas decisiones de diseño del lenguaje.
Jonathan Rich
2
@JonathanRich: ¿por qué no tener% =? Si va a tener alguno de estos operadores de asignación, tarde o temprano algún desarrollador (como penartur) se preguntará por qué los operadores son "más iguales" que otros.
Kevin Cline
44
@JonathanRich Crypto hace un uso significativo del módulo. AdemÃ, hay una ortogonalidad deseado con el resto de la aritmética a los operadores de asignación aritméticas (si se espera +=, *=, -=, /=, ¿por qué no lo haría %=el trabajo?).
44
@JonathanRich: El operador es útil cuando tiene algo circular y desea normalizarlo, por ejemplo, angle %= 360o vertexIndex %= numberOfVertices(para la lista de vértices de un polígono cerrado).
Sebastian Negraszus

Respuestas:

12

Una posible razón es que los operadores lógicos &&y ||tienen un comportamiento de "cortocircuito". El operando derecho de &&y ||no se evalúa a menos que sea necesario. Quizás por esta razón, los diseñadores de lenguaje decidieron que el significado de una expresión como a ||= f()no era obvio, por lo que es mejor dejar de lado a estos operadores.

Kevin Cline
fuente
2
Sí. Por ejemplo, muchas personas creen que a ||= bdebería interpretarse como a = a || b, pero en realidad puede serlo a || a = b(como en Ruby ). Pueden ser diferentes si el setter tiene efectos secundarios. Elegir uno puede ser malo para los usuarios del otro campamento. Personalmente, me gusta el a || a = bcamino (el camino de Ruby), pero no estoy seguro de si todos están contentos con eso.
Franklin Yu
8

La respuesta general a todas las preguntas sobre "por qué no se implementó esta característica del lenguaje" es que el equipo que diseñó el lenguaje decidió que el beneficio no superaba el costo.

El costo puede tomar muchas formas. Implementar una característica del lenguaje requiere tiempo y esfuerzo, pero también existe el costo intrínseco de la complejidad: ¿la característica hace que el lenguaje sea más complejo o ambiguo, en proporción a su beneficio potencial?

El ||=operador hipotético hace algo fundamentalmente diferente de los otros operadores de asignación compuesta. Mientras que los otros operadores son de naturaleza puramente matemática, este es diferente: sustituye un valor por otro (en el contexto que describió).

Dada esta ambigüedad (el operador realiza dos funciones diferentes, según el contexto), no es difícil ver por qué no se incluyó en el lenguaje. Aunque tú afirmas que cambiar

function (options) {
    options = options || {};
}

a

function (options) {
    options ||= {};
}

realizar una fusión nula es una característica valiosa, el beneficio es mucho menos claro para mí. Si se va a producir una sustitución de valores, parece lógico (y más claro) tener ambos valores en el lado derecho del signo igual, para proporcionar una indicación visual de que tal sustitución puede ocurrir.

C # tomó una ruta diferente y utiliza un operador específico para la fusión nula.

Robert Harvey
fuente
1
Al leer el código, el primer ejemplo allí se lee de forma más natural: "las opciones equivalen a opciones o nada", en comparación con el segundo, "las opciones no equivalen a nada". Creo que esta es solo otra razón para no incluir el operador "o igual"
Andy Hunt
Excelente apertura a su respuesta. Y creo que el comienzo de su respuesta pertenece al wiki de la etiqueta.
3
@AndyBursh La misma lógica podría aplicarse a cualquier operador de asignación compuesto. "X es igual a X multiplicado por 2" se lee de forma más natural en comparación con "X multiplicado por 2".
penartur
2
Tenga en cuenta que escribir foo = foo || barrequiere que escriba foodos veces. Esto es engorroso y propenso a refactorizar errores tipográficos.
Phrogz
1
Creo que no entiendes el significado de "matemático", tal vez has oído hablar del álgebra booleana. Estoy de acuerdo en que coaccionar un elemento no booleano para usarlo ||=como operador de fusión nula no es intuitivo y, de hecho, parece obtuso en forma de código. Donde se vuelve útil es cuando intentas hacer matemáticas booleanas. function fulfill(inValue) { if(resolved || rejected) return false; /* Do stuff here */ return true; } resolved ||= fulfill(value)
joshperry
3

Tienes razón, ||=es una construcción útil. Existe en Perl.

De hecho, Perl pone a su disposición todo esto :

**=    +=    *=    &=    <<=    &&=   -=    /=    
|=     >>=   ||=   .=    %=     ^=    //=   x=

Algunos de estos son geniales ( .=agrega algo al final de una cadena), otros no tanto ( &&=supongo que la variable se establecería en el lado derecho si tanto ella como la variable son verdaderas. Pero, ¿por qué harías esto? ?)

Lo que se incluye en un lenguaje es realmente una característica de su filosofía de diseño.


fuente
3
stackoverflow.com/questions/12589467/… para lo que &&=significa / hace.
Mat