Perché non ci sono operatori di assegnazione composti per operatori logici (come ||, && etc)?


20

Secondo ECMA-262, parte 11.13, seguito una lista esaustiva di operatori di assegnazione composti: *= /= %= += -= <<= >>= >>>= &= ^= |=.

Secondo la parte 11.11, var c = a || binserirà avalore in cif ToBoolean(a)è vero e inserirà bvalore in caltrimenti. Pertanto, l' OR logico viene spesso utilizzato come operatore di coalescenza, ad es

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

Abbastanza frequenti, si fondono viene utilizzato per specificare il valore di default per la variabile, come è stato mostrato sopra: a = a || b.

Sembra che operatore di assegnamento composto ||=sarebbe davvero utile, che permette di scrivere il codice di cui sopra in modo più breve e più pulito: a ||= b. Tuttavia, non è presente (sebbene *=, +=e altri operatori di assegnazione composti siano).

La domanda è: perché?


2
Sono incredibilmente perplesso che l'operatore% = esista. Chi ha deciso che era necessario? Alcuni di questi operatori sembrano cattive decisioni di progettazione del linguaggio.
Jonathan Rich

2
@JonathanRich: perché non avere% =? Se hai uno di questi operatori di assegnazione, prima o poi alcuni sviluppatori (come penartur) si chiederanno perché gli operatori siano "più uguali" di altri.
Kevin Cline,

4
@JonathanRich Crypto fa un uso significativo del modulo. Furthemore, v'è un'ortogonalità desiderata con il resto della aritmetica agli operatori di assegnazione aritmetici (se uno si aspetta +=, *=, -=, /=, perché non dovrebbero %=lavoro?).

4
@JonathanRich: l'operatore è utile quando si dispone di qualcosa di circolare e si desidera normalizzarlo, ad esempio angle %= 360o vertexIndex %= numberOfVertices(per l'elenco dei vertici di un poligono chiuso).
Sebastian Negraszus,

Risposte:


12

Una possibile ragione è che gli operatori logici &&e ||hanno un comportamento di "corto circuito". L'operando di destra di &&e ||non viene valutato se non necessario. Forse per questo motivo i progettisti del linguaggio hanno deciso che il significato di un'espressione simile a ||= f()non era ovvio, e quindi tali operatori erano meglio esclusi.


2
Sì. Ad esempio, molte persone credono che a ||= bdovrebbe essere interpretato come a = a || b, ma in realtà può essere a || a = b(come in Ruby ). Possono essere diversi se il setter ha effetti collaterali. Scegliere uno può essere negativo per gli utenti dell'altro campo. Personalmente mi piace il a || a = bmodo (il modo Ruby), ma non sono sicuro che tutti siano contenti di questo.
Franklin Yu,

8

La risposta generale a tutte le domande sul "perché questa funzionalità linguistica non è stata implementata" è che il team che ha progettato la lingua ha deciso che il vantaggio non era superiore ai costi.

Il costo può assumere molte forme. Ci vuole tempo e fatica per implementare una funzione linguistica, ma c'è anche il costo intrinseco della complessità: la funzione rende la lingua più complessa o ambigua, sproporzionata rispetto al suo potenziale beneficio?

L'ipotetico ||=operatore fa qualcosa di sostanzialmente diverso dagli altri operatori di assegnazione composti. Mentre gli altri operatori sono di natura puramente matematica, questo è diverso: sostituisce un valore per un altro (nel contesto che hai descritto).

Data questa ambiguità (l'operatore svolge due diverse funzioni, a seconda del contesto), non è difficile capire perché non sia stato incluso nella lingua. Anche se affermi che cambia

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

per

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

eseguire la coalescenza nulla è una caratteristica preziosa, il vantaggio è molto meno chiaro per me. Se deve avvenire la sostituzione del valore, sembra logico (e più chiaro) avere entrambi i valori sul lato destro del segno uguale, per fornire un'indicazione visiva che tale sostituzione può avvenire.

C # ha preso una strada diversa e utilizza un operatore specifico per la coalescenza nulla.


1
Quando si legge il codice, il primo esempio viene letto in modo più naturale - "opzioni equivalgono a opzioni o niente" - rispetto al secondo - "opzioni o uguale a niente". Penso che questo sia solo un altro motivo per non includere l'operatore "o uguale"
Andy Hunt

Ottima apertura alla tua risposta. E penso che l'inizio della tua risposta appartenga al wiki per il tag.

3
@AndyBursh La stessa logica potrebbe essere applicata a qualsiasi operatore di assegnazione composto. "X equivale a X volte 2" legge in modo più naturale rispetto a "X volte equivale a 2".
penartur

2
Si noti che la digitazione foo = foo || barrichiede di digitare foodue volte. Ciò è al contempo ingombrante e anche soggetto a refusi refactoring.
Phrogz,

1
Penso che tu abbia frainteso il significato di "matematico", forse hai sentito parlare di algebra booleana. Concordo sul fatto che un non-booleano sia obbligato a usarlo ||=come operatore a coalescenza nulla non è intuitivo e in effetti sembra ottuso in forma di codice. Dove diventa utile è quando stai tentando di fare matematica booleana. function fulfill(inValue) { if(resolved || rejected) return false; /* Do stuff here */ return true; } resolved ||= fulfill(value)
joshperry,

3

Hai ragione, ||=è un costrutto utile. Esiste in Perl.

In effetti Perl rende disponibili tutti questi :

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

Alcuni di questi sono fantastici ( .=aggiunge qualcosa alla fine di una stringa), altri meno ( &&=??? Suppongo che la variabile verrebbe impostata sul lato destro se sia la variabile sia vera. Ma perché mai dovresti farlo? ?)

Ciò che è incluso in una lingua è davvero una caratteristica della sua filosofia di design.


3
stackoverflow.com/questions/12589467/… per ciò che &&=significa / fa.
Mat
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.