Чому для логічних операторів (таких як ||, && тощо) немає операторів складеного призначення?


20

У відповідності з ECMA-262, частиною 11.13, Нижче наводиться вичерпний перелік складових операторів присвоювання: *= /= %= += -= <<= >>= >>>= &= ^= |=.

Згідно з частиною 11.11, var c = a || bбуде введено aзначення cif, якщо ToBoolean(a)це правда, і введе bзначення в cінше. Як такий, логічний АБО часто використовується як оператор злиття, наприклад

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

Досить часто, COALESCE використовується для завдання значення за замовчуванням для змінної, як було показано вище: a = a || b.

Звісно ж , що складовою оператор присвоювання ||=буде дуже корисно, що дозволяє писати код , вказаний вище в більш короткі і більш чистою моди: a ||= b. Тим НЕ менше, це не існує (хоча *=, +=і інші оператори присвоювання з'єднання).

Питання в тому, чому?


2
Я неймовірно здивований, що оператор% = навіть існує. Хто вирішив, що це потрібно? Деякі з цих операторів здаються поганими дизайнерськими рішеннями.
Джонатан Річ

2
@JonathanRich: чому б не мати% =? Якщо ви будете мати будь-якого з цих операторів присвоєння, рано чи пізно якийсь розробник (наприклад, penartur) задасться питанням, чому оператори "більш рівні", ніж інші.
Кевін Клайн

4
@JonathanRich Crypto суттєво використовує модуль. Furthemore, є бажана ортогональность з іншою частиною арифметики в арифметичні оператор присвоювання (якщо один очікує +=, *=, -=, /=, чому б не %=працювати?).

4
@JonathanRich: Оператор стане в нагоді, коли у вас є щось кругове і хочете його нормалізувати, наприклад, angle %= 360або vertexIndex %= numberOfVertices(для списку вершин закритого багатокутника).
Себастьян Неграш

Відповіді:


12

Однією з можливих причин є те , що логічні оператори &&і ||мають «коротке замикання» поведінку. Правий операнд о&& і ||не оцінюється, якщо це не потрібно. Можливо, саме тому мовні дизайнери вирішили, що значення виразу на зразок a ||= f()не очевидне, і тому таких операторів краще залишити поза увагою.


2
Так. Наприклад, багато людей вважають, що це a ||= bслід трактувати як a = a || b, але насправді це може бути a || a = b(як у Рубі ). Вони можуть бути різними, якщо сетер має побічну дію. Вибір одного може бути поганим для користувачів в іншому таборі. Мені особисто подобається a || a = bшлях (Рубін), але я не впевнений, чи всі задоволені цим.
Франклін Ю

8

Загальна відповідь на всі запитання про те, "чому ця мовна функція не була реалізована", полягає в тому, що команда, яка розробила мову, вирішила, що користь не перевершує вартість.

Вартість може приймати різні форми. Для впровадження мовної функції потрібен час і зусилля, але є і суттєва вартість складності: чи особливість робить мову більш складною чи неоднозначною, пропорційною її потенційній користі?

Гіпотетичний ||=оператор робить щось принципово відмінне від інших операторів складного призначення. У той час як інші оператори мають суто математичний характер, цей відрізняється: він замінює одне значення іншим (у контексті, який ви описали).

Враховуючи цю неоднозначність (оператор виконує дві різні функції, залежно від контексту), не важко зрозуміти, чому він не був включений у мову. Хоча ви заявляєте, що змінюється

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

до

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

виконувати нульове з’єднання - цінна особливість, користь для мене набагато менш зрозуміла. Якщо відбудеться заміна значень, здається логічним (і зрозумілішим) обидва значення з правого боку знака рівності, щоб забезпечити візуальну ознаку того, що таке підміна може відбуватися.

C # взяв інший шлях і використовує певний оператор для нульового з’єднання.


1
Читаючи код, перший приклад там читається більш природно - "параметри дорівнюють опціям або нічого" - порівняно з другим - "параметри або дорівнює нічого". Я думаю, що це лише ще одна причина не включення оператора "або рівних"
Енді Хант

Відмінне відкриття до вашої відповіді. І я думаю, що початок вашої відповіді належить у вікі для тегу.

3
@AndyBursh Ця ж логіка може бути застосована до будь-якого оператора присвоєння складних завдань. "X дорівнює X разів 2" читається природніше, ніж "X разів дорівнює 2".
пенатур

2
Зауважте, що для введення тексту foo = foo || barпотрібно ввести fooдвічі. Це одночасно громіздко, а також схильне до помилок рефакторингу.
Фрогз

1
Я думаю, ви неправильно розумієте значення "математичного", можливо, ви чули про булеву алгебру. Я погоджуюсь, що примушування не булевим для того, щоб використовувати його ||=як оператор, що поєднує нуль, не є інтуїтивно зрозумілим і насправді виглядає тупою у вигляді коду. Де це стає корисним - це коли ви намагаєтеся займатися булевою математикою. function fulfill(inValue) { if(resolved || rejected) return false; /* Do stuff here */ return true; } resolved ||= fulfill(value)
joshperry

3

Ви праві, що ||=це корисна конструкція. Він існує в Perl.

Насправді Perl робить все це доступним:

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

Деякі з них є чудовими ( .=додає щось до кінця рядка), інші - менш ( &&=??? Я думаю, що змінна встановиться у праву сторону, якщо і вона, і змінна є правдою. Але чому б ти коли-небудь робив це ?)

Те, що входить до мови, є дійсно особливістю її філософії дизайну.


3
stackoverflow.com/questions/12589467/… про те, що &&=означає / робить.
Мат
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.