2010-10-18 2 views
14

Возможные Дубликаты:
Why doesn't Java have compound assignment versions of the conditional-and and conditional-or operators? (&&=, ||=)
Why does a “&&=” Operator not exist?&& = и || = операторы

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

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

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

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

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

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

+0

Да, у вас могут быть два «истинных» логических значения (оба больше одного), где их побитовое и значение «false» ... Попробуйте побитовое и 2 и 1, и вы получите 0 (false), где логический и будет выдавать true – LorenVS

+2

'b & = isSomethingWithSideEffects();' будет запускать функцию независимо. но если он был изменен на '&& =' предположительно, это не было бы в случае, если b был ложным, нет? – Dusty

+1

Извините, я не понимаю, почему комментарий Динго был поддержан. Может ли кто-нибудь объяснить, пожалуйста? – John

ответ

8

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

Существует абсолютно никаких проблем с коротким замыканием при определении &&= и ||= операторов. Они должны быть определены равномерно с += и другими аналогичными операторами, что означает, что a &&= b должен быть эквивалентен a = a && b, но с a оценивается только один раз в версии &&=. Это, в свою очередь, означает, что b не оценивается вообще, если a изначально равен нулю. Легко.

Таким образом, единственная причина, по которой они не существуют на этом языке, - это «просто потому, что».

+1

Точно. У Perl есть эти операторы с этим поведением; и, хотя я слышал много критических замечаний о Perl, я никогда не слышал, чтобы кто-то жаловался, что '&& =' запутывает. – Porculus

+0

Хорошая точка в отношении короткого замыкания, но технически говоря a = a + b не эквивалентна + = b, если a имеет побочные эффекты, например. это функция, печатающая что-то и возвращающая ссылку (в первом случае будет печататься дважды, а во втором - только один раз). –

+0

@Armen Tsirunyan: Ну, я не пытался сделать его официально префектом. Стандарт языка определяет 'a + = b' как эквивалент' a = a + b', за исключением того, что в '+ =' version 'a' оценивается только один раз. Точно так же можно определить '&& ='. – AnT

0

EDIT: Неправильный язык, но до сих пор применяется

Я согласен с вашими тремя причинами, хотя есть один сценарий, в котором я посетовал на отсутствие этого оператора, при написании пользовательских десериализации процедур. В нескольких случаях, когда неправильно сериализованный объект не был действительно «исключительным» (и чтобы исключить накладные расходы на 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; 
    } 
} 
+0

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

+0

В этом случае вы можете просто «вернуть false» раньше. –

+0

Я ответил на свой вопрос :) –

9

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

Еще одним фактором, способствующим тому, что C предназначен для работы вблизи металла, в значительной степени все операторы соответствуют инструкциям в основных архитектурах. Я не думаю, что есть инструкция по x86, PPC и т. Д., Которые непосредственно реализуют b &&= b1;

+1

+1. Какие операции были доступны на PDP-11, вероятно, более сдерживающим фактором, но я все еще думаю, что вы на что-то там. –

+0

@ T.E.D .: Конечно, но современные крупные архитектуры наследуют основную часть своих инструкций от архитектурных решений. Особенно в общих помещениях. –

+0

А? Короткое замыкание - это аргумент * для * них. Без этого просто используйте '& =' с булевыми значениями. Что касается инструкций, то те же самые используются как для 'b && (b = b1);', (но только с одной оценкой 'b'). Компилятор выбирает между ветвью и поразрядным И. – Potatoswatter

1

Лично я проголосовал за первое обоснование, с которым вы пошли. Булевы операторы имеют короткозамкнутую семантику, которая могла бы привести к некоторым действительно грубым ситуациям, если они переведены в операторы присваивания. Либо вы больше не делаете их короткозамкнутым, либо создали какой-то странный «необязательный» оператор присваивания (делайте вещи справа и присваивайте результат, только если значение на LHS уже отличное от нуля). В любом случае вы создадите тонкие ошибки, потому что люди будут ожидать другого поведения.

2

Основная причина, по которой операторы не существуют, вероятно, состоит в том, что K & R не думал ни о каком привлекательном способе их определения. Мне также иногда нужен оператор -> = (ptr -> = next будет эквивалентен ptr = ptr-> независимо).

проблема, я думаю, что с & & = является то, что это не очевидно, что из перечисленного будет наиболее полезным, или которые он должен быть:

 
    if (lhs && rhs) lhs = 1; else lhs = 0; 
    if (!rhs) lhs = 0; else lhs = !(!lhs)); 
    if (lhs && !rhs) lhs = 0; 
    if (!rhs) lhs = 0; 
Первый вариант является одним из наиболее четко предложил синтаксисом, но из практическая точка зрения, если ни один из них не равен нулю, часто было бы более полезно оставить левую сторону в одиночку, чем установить ее в «1».

BTW, я часто хотел, чтобы вариация оператора запятой оценивала левую сторону, сохраняла значение, затем оценивала правую сторону и возвращала значение левой стороны. Эквивалент:

 
int foo(int p1, int p2) return p1; 
, за исключением применимого к любому типу (p2 не обязательно должен быть того же типа, что и p1, и может быть недействительным) и с гарантированным порядком оценки слева направо. Было бы очень удобно для таких вещей, как индексирование после инкремента с помощью не единичного шага, например arr [ptr ~, ptr + = 2]; или для определенных типов операций обмена данными, например var1 = (var2 ~, var2 = var1); и т. д.

+3

В C все составные операторы присваивания ('op =') определяются как 'lhs = lhs op rhs', причем выражение' lhs' оценивается только один раз. Поэтому я думаю, что существует небольшая двусмысленность относительно того, как будет определяться '&& =' (таким же образом). –

+0

@Michael Burr: Это было бы sytactically естественной реализацией, но на практике бывают времена, когда третий был бы более полезен, чем первый, но я не могу думать о том, как много, где первое на самом деле было бы более полезным. – supercat

+1

Я предложил этот эквивалент теперь удаленному вопросу: 'if (lhs) lhs = (rhs! = 0);' Кажется, имеет ожидаемое короткое замыкание. Тем не менее, вероятно, быстрее выполнить 'if (lhs) lhs = rhs;', который также является коротким замыканием, но не принуждает все ненулевые значения к 1. –

2

Поскольку результат a && b всегда 0 или 1, я думаю, что интерпретация этого будет только однозначной для типа C99 _Bool. Поскольку этого не существовало в момент создания C, этот оператор тогда не включался. И в настоящее время никто не может добавить другого оператора в C, поскольку это повлияет на все существующие синтаксические анализаторы.

Смежные вопросы