Dlaczego nie istnieją operatory przypisania złożonego dla operatorów logicznych (takich jak ||, && itp.)?

20

Według ECMA-262, strony 11.13 następuje to wyczerpująca lista związków operatorów przypisania: *= /= %= += -= <<= >>= >>>= &= ^= |=.

Zgodnie z częścią 11.11, var c = a || bwprowadzi awartość do cjeżeli ToBoolean(a)jest prawdą i wprowadzi bwartość do cinaczej. Jako taki, logiczny OR jest często używany jako operator koalescencji, np

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

Często wystarczy, COALESCE służy do określenia wartości domyślnej zmiennej, jak wykazano powyżej: a = a || b.

Wydaje się, że związek operator przypisania ||=byłaby bardzo przydatna, umożliwiając napisać powyższy kod w krótszym i czystszego sposób: a ||= b. Jednakże, nie ma (chociaż *=, +=a operatorami przypisania czynnych wynoszą).

Pytanie brzmi: dlaczego?

penartur
źródło
2
Jestem niesamowicie zakłopotany, że operator% = w ogóle istnieje. Kto uznał, że to konieczne? Niektóre z tych operatorów wydają się być złymi decyzjami dotyczącymi projektowania języka.
Jonathan Rich
2
@JonathanRich: dlaczego nie mieć% =? Jeśli masz któregoś z tych operatorów przypisań, prędzej czy później jakiś programista (np. Penartur) będzie się zastanawiał, dlaczego operatorzy są „bardziej równi” niż inni.
kevin cline
4
@JathanathanRich Crypto znacząco wykorzystuje moduł. Furthemore, jest pożądane ortogonalności z resztą arytmetyki do arytmetycznych operatorów przypisania (jeśli oczekuje +=, *=, -=, /=, dlaczego nie %=działa?).
4
@JathanathanRich: Operator przydaje się, gdy masz coś okrągłego i chcesz go znormalizować, np. angle %= 360Lub vertexIndex %= numberOfVertices(dla listy wierzchołków zamkniętego wielokąta).
Sebastian Negraszus

Odpowiedzi:

12

Jedną z możliwych przyczyn jest to, że operatory logiczne &&i ||ma zachowanie „zwarcie”. Argument po prawej stronie &&i ||nie jest oceniany, chyba że jest to konieczne. Być może z tego powodu projektanci języków zdecydowali, że znaczenie takiego wyrażenia a ||= f()nie jest oczywiste, dlatego lepiej pominąć takie operatory.

Kevin Cline
źródło
2
Tak. Na przykład wiele osób uważa, że a ||= bnależy to interpretować jako a = a || b, ale tak naprawdę może być a || a = b(jak w Ruby ). Mogą się różnić, jeśli seter ma efekt uboczny. Wybór jednego może być zły dla użytkowników w drugim obozie. Osobiście podoba mi się ten a || a = bsposób (sposób Rubinowy), ale nie jestem pewien, czy wszyscy są z tego zadowoleni.
Franklin Yu,
8

Ogólna odpowiedź na wszystkie pytania dotyczące „dlaczego ta funkcja języka nie została zaimplementowana” jest taka, że ​​zespół, który zaprojektował ten język, uznał, że korzyść nie przewyższa kosztów.

Koszt może przybierać różne formy. Wdrożenie funkcji językowej wymaga czasu i wysiłku, ale wiąże się to również z wewnętrznym kosztem złożoności: czy funkcja sprawia, że ​​język jest bardziej złożony lub niejednoznaczny, nieproporcjonalny do jego potencjalnych korzyści?

||=Operator hipotetyczny robi coś zasadniczo odmiennego od innych operatorów przypisań złożonych. Podczas gdy inne operatory mają charakter czysto matematyczny, ten jest inny: zastępuje jedną wartość inną (w opisanym kontekście).

Biorąc pod uwagę tę dwuznaczność (operator wykonuje dwie różne funkcje, w zależności od kontekstu), nietrudno zrozumieć, dlaczego nie został uwzględniony w języku. Chociaż twierdzisz, że to się zmienia

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

do

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

wykonanie koalescencji zerowej jest cenną cechą, korzyść jest dla mnie o wiele mniej oczywista. Jeśli ma nastąpić podstawienie wartości, logiczne (i wyraźniejsze) wydaje się posiadanie obu wartości po prawej stronie znaku równości, aby zapewnić wizualne wskazanie, że taka zamiana może wystąpić.

C # obrał inną ścieżkę i używa określonego operatora do koalescencji zerowej.

Robert Harvey
źródło
1
Podczas czytania kodu pierwszy przykład brzmi bardziej naturalnie - „opcje równa się opcjom lub nic” - w porównaniu do drugiego - „opcje lub nic nie równa”. Myślę, że jest to kolejny powód, dla którego nie uwzględniono operatora „lub równego”
Andy Hunt
Doskonałe otwarcie na twoją odpowiedź. I myślę, że początek twojej odpowiedzi należy do wiki tagu.
3
@AndyBursh Tę samą logikę można zastosować do dowolnego operatora przypisania złożonego. „X równa się X razy 2” czyta bardziej naturalnie w porównaniu do „X razy równa się 2”.
penartur
2
Pamiętaj, że pisanie foo = foo || barwymaga foodwukrotnego wpisania . Jest to zarówno uciążliwe, jak i podatne na refaktoryzację literówek.
Phrogz
1
Myślę, że źle rozumiesz znaczenie „matematyki”, być może słyszałeś o algebrze boolowskiej. Zgadzam się, że wymuszanie nie-logicznej wartości w celu użycia ||=jako zerowego operatora koalescencyjnego nie jest intuicyjne i w rzeczywistości wygląda tępo w formie kodu. Przydaje się, gdy próbujesz wykonać matematykę boolowską. function fulfill(inValue) { if(resolved || rejected) return false; /* Do stuff here */ return true; } resolved ||= fulfill(value)
joshperry
3

Masz rację, ||=to jest przydatna konstrukcja. Istnieje w Perlu.

W rzeczywistości Perl udostępnia wszystkie te elementy :

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

Niektóre z nich są świetne ( .=dodaje coś na końcu łańcucha), inne mniej ( &&=??? Przypuszczam, że zmienna zostałaby ustawiona po prawej stronie, jeśli zarówno ona, jak i zmienna są prawdziwe. Ale dlaczego miałbyś to robić? ?)

To, co jest zawarte w języku, jest tak naprawdę cechą jego filozofii projektowania.


źródło
3
stackoverflow.com/questions/12589467/ ... co &&=oznacza / robi.
Mat.