Причина существования некоротких логических операторов

При использовании с boolean операндами & и | становятся логическими операторами в разделе 15.22.2 JLS . В отличие от && и || , однако, они не замыкаются; они всегда оценивают обе стороны. У меня есть глупый вопрос: почему все еще существуют менее эффективные логические операторы с коротким замыканием ( & , | ), когда у нас есть более эффективные логические операторы короткого замыкания ( && , || )? Я имею в виду, каково реальное использование логических операторов без коротких замыканий, в отличие от логических операторов короткого замыкания? Другими словами, каково использование всегда оценки обеих сторон с помощью некоротких логических операторов?

Обновленный ответ :

Извиняюсь, я пропустил слово «логично» в вашем вопросе, хотя оно есть. (Я позволил немного подчеркнуть это с помощью редактирования).

Рассмотрим случай, когда вы хотите, чтобы любые побочные эффекты всегда возникали, независимо от того, оценивает ли левое выражение true или false . Например, контраст:

 if (foo() & bar()) { // Only call this if both operations returned true } 

с

 if (foo() && bar()) { // Only call this if both operations returned true } 

Предположим, что у foo и bar есть эффекты, которые мы хотим выполнить независимо от того, возвращает ли foo true или false . В первом выше, я знаю, что bar всегда будет вызван и будет иметь эффект. В последнем, конечно, bar может или не может быть вызван. Если бы у нас не было версии с коротким замыканием, нам пришлось бы использовать временные переменные:

 boolean fooResult, barResult; fooResult = foo(); barResult = bar(); if (fooResult && barResult) { // ... } 

Вы могли бы возразить (я, вероятно, буду), что вы все равно должны это делать, потому что слишком легко ошибиться, if (foo() & bar()) , но там мы идем, прагматичная причина наличия версий с коротким замыканием.

Оригинальный ответ :

Как вы предлагаете & (или | ) быть короткозамкнутым оператором? С && и || , это имеет смысл, потому что вы имеете дело с булевыми условиями: они могут быть истинными или ложными, нет оттенков серого. Но & и | иметь дело с битами, а не булевыми. Результатом является число. Я имею в виду, я думаю, & не мог оценить правую часть, если левая часть равна 0 , и аналогично | не мог оценить его, если левая сторона была полностью битовой для любого типа, но я не вижу большого смысла, чтобы сделать один крайный случай каждого оператора значительным (по сравнению с 254 или более другими случаями ).

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

 while ( !password.isValid() & (attempts++ < MAX_ATTEMPTS) ) { // re-prompt } 

Если второе условие не было оценено из-за короткого замыкания, attempts никогда не будут увеличиваться. Таким образом, обеспечивается более высокая гибкость программиста.

Мой случай (C ++):

 void setFields(Parameters bundle) { if (setIfDifferent(&field1, bundle.value1) | setIfDifferent(&field2, bundle.value2) | setIfDifferent(&field3, bundle.value3)) { storeState(); } } 

setIfDifferent () устанавливает поле объекта с новым значением, если они отличаются, и в этом случае он возвращает true; или он возвращает false, если поле и новое значение совпадают. Итак, мы хотим попытаться установить все поля, и если какой-либо из них изменился, то мы хотим сохранить состояние нового объекта.

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

Не могу вспомнить хороший пример сейчас, но помните, что мне иногда нужны операторы «короткого замыкания».

Hmmm …. Ниже пример WRONG, который не будет работать без «короткого замыкания» ИЛИ:

 if( (object1=getInstance1()).getNumber() == 1 || (object2=getInstance2()).getNumber() == 2 ) { // do something which requires bot object1 and object2 assigned } 

В моем случае у меня есть два метода, которые сравнивают два разных, но связанных объекта (Object2 – это атрибут Object1), чтобы увидеть, были ли какие-либо изменения. Обновление должно выполняться, если либо обновлено, но и то, и другое нужно оценивать, чтобы объекты были изменены, если они были изменены. Поэтому требуется однократное сравнение «ИЛИ».

EX:

 if (compare(object1, currentObject1) | comparison(object2, currentObject2)) { updateObject1(object1); } 

Технически, & и | не являются логическими, они являются побитовыми операторами, которые становятся логическими операторами, когда они связаны с булевыми.

Бывают случаи, когда вы хотите включить выражения присваивания в свои логические выражения.

Сказать:

 if(a = (checkForSomeCondition()) | b = checkForAnotherCondition()) { //now do something here with a and b that has been cached } 

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

Конечно, вы можете использовать унарные операторы в логических выражениях или передавать переменные по ссылке в предикат, но они выглядят как менее распространенные случаи, чем выше.

  • Булевы операторы && и ||
  • Являются ли закодированные логические операторы короткими законами? И порядок оценки?
  • В чем разница между логическим и условным И, ИЛИ в C #?
  • Простые логические операторы в Bash
  • Различия в булевых операторах: & vs && и | vs ||
  • В чем разница между & и && в MATLAB?
  • Давайте будем гением компьютера.