Почему нет сложных операторов присваивания для логических операторов (таких как ||, && и т. Д.)?

20

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

В соответствии с частью 11.11, значение var c = a || bбудет помещено в aзначение true, cесли ToBoolean(a)оно истинно, а bзначение в cдругое значение . Как таковой, логическое ИЛИ часто используется как оператор объединения, например

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

Достаточно часто, COALESCE используется для задания значения по умолчанию для переменной, как было показано выше: a = a || b.

Представляется , что составной оператор присваивания ||=будет очень полезно, что позволяет писать код , указанный выше в более короткие и более чистой моды: a ||= b. Тем не менее, это не существует (хотя *=, +=и другие операторы присваивания соединения).

Вопрос в том, почему?

penartur
источник
2
Я невероятно озадачен тем, что оператор% = даже существует. Кто решил, что это необходимо? Некоторые из этих операторов кажутся плохими решениями по проектированию языка.
Джонатан Рич
2
@JonathanRich: почему бы не иметь% =? Если у вас будет какой-либо из этих операторов присваивания, рано или поздно какой-нибудь разработчик (например, penartur) спросит, почему операторы «более равны», чем другие.
Кевин Клайн
4
@JonathanRich Crypto широко использует модуль. Furthemore, есть желаемая ортогональность с остальной частью арифметики в арифметические оператор присваивания (если один ожидает +=, *=, -=, /=, почему бы не %=работать?).
4
@JonathanRich: Оператор пригодится, когда у вас есть что-то круглое и вы хотите его нормализовать, например, angle %= 360или vertexIndex %= numberOfVertices(для списка вершин замкнутого многоугольника).
Себастьян Неграсус
1
Обратите внимание, что в 2007 году (кто-то утверждает, что это так) Брендан Айх объявил об этом ||=и &&=скоро будет: «Возможно, вы будете рады узнать, что для JS2 / ES4 также добавляются || = и && =. полезный из двух, но нет никаких причин оставлять опциональную форму && вне. " ,
Phrogz

Ответы:

12

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

Кевин Клайн
источник
2
Да. Например, многие люди считают, что это a ||= bследует интерпретировать как a = a || b, но на самом деле это может быть a || a = b(как в Ruby ). Они могут отличаться, если у сеттера есть побочный эффект. Выбор одного может быть плох для пользователей в другом лагере. Мне лично нравится a || a = bпуть (путь Руби), но я не уверен, довольны ли все этим.
Франклин Ю
8

Общий ответ на все вопросы о том, «почему эта языковая функция не была реализована», заключается в том, что команда, разработавшая язык, решила, что выгода не перевесит стоимость.

Стоимость может принимать разные формы. Для реализации языковой функции требуются время и усилия, но есть и внутренняя стоимость сложности: делает ли функция язык более сложным или неоднозначным, не пропорционально его потенциальной выгоде?

Гипотетический ||=оператор делает что-то принципиально отличное от других составных операторов присваивания. В то время как другие операторы имеют чисто математический характер, этот отличается от других: он заменяет одно значение другим (в контексте, который вы описали).

Учитывая эту неоднозначность (оператор выполняет две разные функции в зависимости от контекста), нетрудно понять, почему он не был включен в язык. Хотя вы утверждаете, что изменение

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

в

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

Выполнение нулевого слияния является ценной особенностью, но для меня это гораздо менее очевидно. Если должно произойти подстановка значений, кажется логичным (и более понятным) иметь оба значения справа от знака равенства, чтобы обеспечить визуальную индикацию того, что такая замена может произойти.

C # выбрал другой путь и использует специальный оператор для объединения нулей.

Роберт Харви
источник
1
При чтении кода первый пример там читается более естественно - «параметры равны параметрам или ничего» - по сравнению со вторым - «параметры или равны ничему». Я думаю, что это просто еще одна причина, по которой мы не включили оператор "или равно"
Энди Хант,
Отличное открытие для вашего ответа. И я думаю, что начало вашего ответа принадлежит вики для тега.
3
@AndyBursh Та же логика может быть применена к любому составному оператору присваивания. «X равно X умножить на 2» читается более естественно по сравнению с «X умножено на 2».
penartur
2
Обратите внимание, что при наборе текста foo = foo || barвы должны печатать fooдважды. Это и громоздко, и также склонно к рефакторингу опечаток.
Phrogz
1
Я думаю, что вы неправильно понимаете значение «математического», возможно, вы слышали о булевой алгебре. Я согласен, что приведение не-логического значения для использования ||=в качестве нулевого оператора объединения не является интуитивно понятным и на самом деле выглядит тупо в кодовой форме. Где это действительно полезно, когда вы пытаетесь сделать булеву математику. function fulfill(inValue) { if(resolved || rejected) return false; /* Do stuff here */ return true; } resolved ||= fulfill(value)
Джошперри
3

Вы правы, что ||=это полезная конструкция. Он существует в Perl.

На самом деле Perl делает все это доступным:

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

Некоторые из них хороши ( .=добавляет что-то в конец строки), другие - нет ( &&=???. Я полагаю, что переменная будет установлена ​​в правую часть, если и она, и переменная верны. Но зачем вам это делать? ?)

То, что включено в язык, действительно является чертой его философии дизайна.


источник
3
stackoverflow.com/questions/12589467/… что &&=означает / делает.
Мат