&&= и ||= операторы
Возможные дубликаты:
Почему в Java нет составных версий условных и условных операторов? (&&=, || =)
Почему оператор "&&=" не существует?
Сегодня на работе я написал следующий LOC (реальные имена b и b1 являются конфиденциальными:)
b &&= b1; // meaning b = b && b1;
Я смотрел на него пару секунд и понял, что такого оператора не существует. Просто чтобы быть уверенным, я нажал на компиляцию, и она не удалась. Чтобы быть уверенным, я справился со стандартом.
Есть ли конкретные причины, по которым таких операторов нет? Я могу думать о некоторых:
b &&= b1
а такжеb = b && b1
может быть не эквивалентно из-за оценки короткого замыкания &&.- &&= уродливо
- &&= редко требуется
Я не утверждаю, что было бы очень полезно иметь такие операторы, нет. Я также не утверждаю, что какой-либо или всех трех вышеперечисленных причин недостаточно, чтобы воздержаться от создания этого оператора. У меня следующий вопрос: может быть, есть более серьезная причина, которую я наблюдаю?
6 ответов
Я не знаю, почему и в вопросе, и в некоторых ответах упоминается короткое замыкание соответствующих логических операторов в качестве потенциальной проблемы.
Там нет абсолютно никаких связанных с коротким замыканием проблем с определением &&=
а также ||=
операторы. Они должны быть определены с +=
и другие подобные операторы, что означает, что a &&= b
должно быть эквивалентно a = a && b
, но с a
оценивается только один раз в &&=
версия. Это в свою очередь означает, что b
не оценивается вообще, если a
изначально ноль. Легко.
Итак, единственная причина, по которой они не существуют в языке, это "просто потому что".
Я хотел их и раньше. Я сомневаюсь, что безобразие само по себе является определяющим фактором, короткое замыкание - лучший аргумент против них, который я слышал до сих пор.
Еще одним фактором, способствующим этому, является то, что C предназначен для работы близко к металлу, почти все операторы напрямую соответствуют инструкции в основных архитектурах. Я не думаю, что есть инструкция на x86, PPC и т. Д., Которая непосредственно реализует b &&= b1;
Потому что результат a && b
всегда 0
или же 1
Я думаю, что толкование этого было бы только однозначно для C99 _Bool
тип. Поскольку его не было на момент создания C, этот оператор не был включен. И в настоящее время никто не может легко добавить еще один оператор в C, так как это повлияет на все существующие парсеры.
Основная причина, по которой операторы не существуют, - это, вероятно, то, что K&R не придумал какого-либо привлекательного способа их определения. Я также иногда хотел оператор ->= (ptr->=next будет эквивалентно ptr = ptr-> как угодно).
Я думаю, что проблема с &&= заключается в том, что неясно, какой из следующих пунктов будет наиболее полезным или каким он должен быть:
if (lhs && rhs) lhs = 1; иначе lhs = 0; if (!rhs) lhs = 0; иначе lhs =!(!lhs)); if (lhs &&!rhs) lhs = 0; if (!rhs) lhs = 0;Первый вариант наиболее четко предложен синтаксисом, но с практической точки зрения, если ни один из терминов не равен нулю, часто было бы более полезно оставить левую часть в одиночку, чем установить ее в "1".
Кстати, я часто хотел иметь вариант оператора запятой, который будет оценивать левую сторону, сохранять значение, затем оценивать правую сторону и возвращать значение левой стороны. Эквивалентно:
int foo (int p1, int p2) return p1;кроме применимых к любому типу (p2 не обязательно должен быть того же типа, что и p1, и может быть недействительным), и с гарантированным порядком оценки слева направо. Было бы очень удобно для таких вещей, как индексирование после инкремента с шагом, не равным единице, например, arr[ptr ~, ptr+=2]; или для определенных типов операций обмена данными, например, var1 = (var2 ~, var2=var1); и т.п.
Лично я бы проголосовал за первое обоснование, с которым вы пошли. Булевы операторы имеют семантику короткого замыкания, которая может привести к некоторым действительно сложным ситуациям, если их преобразовать в операторы присваивания. Либо вы больше не делаете их короткими замыканиями, либо создали какой-то странный "необязательный" оператор присваивания (сделайте все справа и присвойте результат только в том случае, если значение на LHS уже ненулевое). В любом случае вы могли бы создавать тонкие ошибки, потому что люди ожидали бы другого поведения.
РЕДАКТИРОВАТЬ: неправильный язык, но все еще применяется
Я согласен с вашими тремя причинами, хотя есть один сценарий, в котором я сетовал на отсутствие этого оператора при написании пользовательских процедур десериализации. В паре случаев, когда неправильно сериализованный объект не был действительно "исключительным" (и для предотвращения издержек исключения в C# для очень распространенных сбоев), я использовал бы логические возвращаемые значения, чтобы показать, была ли операция десериализации успешной.
Этот код является полностью теоретическим, и Nested1, Nested2 и Nested3 являются структурами:
public struct ComplexStruct
{
private Nested1 nested1;
private Nested2 nested2;
private Nested3[] nested3;
public bool Read(Reader reader)
{
bool ret = true;
int nested3Length = 0;
ret &&= nested1.Read(reader);
ret &&= nested2.Read(reader);
ret &&= reader.ReadInt32(ref nested3Length);
for(int i = 0; (ret && i < nested3Length); i++)
{
ret &&= nested3[i].Read(reader);
}
return ret;
}
}