&&= и ||= операторы

Возможные дубликаты:
Почему в Java нет составных версий условных и условных операторов? (&&=, || =)
Почему оператор "&&=" не существует?

Сегодня на работе я написал следующий LOC (реальные имена b и b1 являются конфиденциальными:)

b &&= b1; // meaning b = b && b1; 

Я смотрел на него пару секунд и понял, что такого оператора не существует. Просто чтобы быть уверенным, я нажал на компиляцию, и она не удалась. Чтобы быть уверенным, я справился со стандартом.

Есть ли конкретные причины, по которым таких операторов нет? Я могу думать о некоторых:

  1. b &&= b1 а также b = b && b1 может быть не эквивалентно из-за оценки короткого замыкания &&.
  2. &&= уродливо
  3. &&= редко требуется

Я не утверждаю, что было бы очень полезно иметь такие операторы, нет. Я также не утверждаю, что какой-либо или всех трех вышеперечисленных причин недостаточно, чтобы воздержаться от создания этого оператора. У меня следующий вопрос: может быть, есть более серьезная причина, которую я наблюдаю?

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;
    }
}
Другие вопросы по тегам