Навіщо використовувати! Boolean_variable Over boolean_variable == false


60

Коментар до цього питання: Перевірка, чи метод повертає false: призначити результат тимчасовій змінній, або поставити виклик методу безпосередньо в умовний? говорить, що ви повинні використовувати !booleanзамість цього boolean == falseпри тестуванні умов. Чому? Для мене boolean == falseнабагато природніше англійська мова і більш чітка. Прошу вибачення, якщо це лише питання стилю, але мені було цікаво, чи є якась інша причина такої переваги !boolean?


28
Писати коротше.
Зенон

39
Це як робити boolean == true: це не має сенсу. Вираження всередині ifвисловлювань - це саме те, що: вирази. Якщо щось вже оцінює булевий вираз, то чому б ви додали чек, щоб змусити його оцінювати це?
Maxpm

10
@zzzzBov: Гм, ні. Це не так, як це роблять більшість програмістів (у стилі С).
amara

9
@zzzzBov: Ваш коментар неоднозначний. Якщо ви мали на увазі !boolean_variableсаме так, як це роблять більшість програмістів на C, я згоден.
Кіт Томпсон,

29
І ще важливіше, як так ніхто не хоче писати boolean != true?

Відповіді:


153

Коли я бачу такий рядок if (!lateForMeeting()), я читаю це як "Якщо не спізнився на зустріч" , що зрозуміло досить просто, на відміну від того, if (lateForMeeting() == false)який я читав би як "Якщо факт, що я спізнююся на зустріч, неправдивий " .

Вони за значенням однакові, але перше ближче до того, як було б побудовано рівнозначне англійське речення.


27
+1 На Python ви насправді пишете if not late_for_meeting:)
phunehehe

42
Я стверджую, що якщо "якщо ___ помилково" звучить більш природно, ніж "якщо не ___", то ім'я ___ потребує вдосконалення.
Майк Десимоне,

12
У Perl можна написатиunless late_for_meeting
Генрік Ріпа

4
@HenrikRipa: Схоже, майже все, що ви можете набрати, це юридичний код у Perl. Чи це робить те, що ви хочете, інше питання;)
Адам Робінсон

4
@ A-Cube У мене не було б такого способу для початку. Натомість у мене був би метод, який називається done(). Подвійні негативи погані.
kba

97

Написання == falseі == trueзайве. Це також можна сприймати до довільних крайнощів. Якщо ви почнете писати

if (condition == false) { ... }

Тоді чому б і ні

if ((condition == false) == true) { ... }

Або чому ні

if ((someExp == anotherExp) == true) { ... }

Мораль цієї історії полягає в тому, що якщо conditionбулевий вираз, то вам не потрібно додавати == false; ось для чого оператор !;)


Не думав про це!
ell

51
== falseНЕ зайве, просто більш багатослівне, ніж !. OTOH, == trueє зайвим.
dan04

4
@ dan04 Ви маєте рацію. Однак у тому сенсі, який я мав на увазі, це залишається поганою ідеєю. Розглянемо (exp1 != exp2)проти ((exp1 == exp2) == false). Справді, це надумані сценарії, але все ж майже ніколи не слід писати явних порівнянь з істинним чи хибним. Як ви повинні використовувати оператор !=, так і ви повинні використовувати !.
Андрес Ф.

26
@ dan04: Це зайве, коли мова вже пропонує !.
DeadMG

5
@ dan04: Кожен раз, коли ви пишете bool_expression == bool_literal, == ...це зайве . Незалежно від того, тестуєте ви на справжнє чи хибне, не має значення. Це лише зміна порядку послідовних / альтернативних блоків. Приклади Андреса прекрасно ілюструють цю точку. Більшість сучасних компіляторів оптимізують надмірність, але це все-таки зайве.
Lèse majesté

70

В C і деяких подібних мовах, порівнюючи логічні вирази для рівності falseабо trueнебезпечна звичка.

У C будь-який скалярний вираз (числовий або покажчик) може використовуватися в булевому контексті, наприклад, як умова ifтвердження. Правило C таке, що if (cond)еквівалентно if (cond != 0)- тобто нуль є помилковим, а будь -яке ненульове значення - істинним. Якщо condтип вказівника, 0трактується як нульова константа вказівника; if (ptr)засоби if (ptr != NULL).

Це означає що

if (cond)

і

if (cond == true)

не означають те саме . Перша вірна, якщо condне дорівнює нулю; друге справедливо лише в тому випадку, якщо воно дорівнює true, що в C (якщо у вас є #include <stdbool.h>) просто 1.

Наприклад, isdigit()функція, оголошена у <ctype.h>повертанні, повертає intзначення, 0якщо аргумент - це цифра, не нуль, якщо це не так. Він може повернутися, 42щоб вказати, що умова справжня. Порівнювати 42 == trueне вдасться.

Буває, що 0це єдине значення, яке вважається помилковим, тому порівняння для рівності falseбуде спрацьовувати; if (!cond)і if (cond == false)робити те саме. Але якщо ви збираєтеся скористатися цим, ви повинні пам’ятати, що зіставляти falseце нормально, а порівнювати true- ні. Що ще гірше, порівняно з тим, що trueбуде працювати більшу частину часу (наприклад, оператори рівності та реляційні завжди дають або 0або 1). Це означає, що будь-які помилки, які ви вводите за допомогою цього, все ще може бути важко відстежити. (Не хвилюйтесь, вони з’являться, як тільки ви демонструєте код важливому клієнту.)

C ++ має дещо інші правила; наприклад, його boolтип трохи тісніше інтегрується в мову і if (cond)перетворюється condна тип bool. Але ефект (в основному) той самий.

Деякі інші мови мають те, що можна назвати булевими, що поводиться краще, таким, що cond == trueі cond == false(або що б не було синтаксисом) є безпечним. Тим не менш, кожна мова, яку я бачив, має notабо !оператора; він є, тому ви також можете використовувати його. Використання cond == falseзамість !condабо not condнемає, на мій погляд, поліпшити читаність. (Це правда, що !персонажа може бути важко побачити з першого погляду; я іноді додаю пробіл після цього, !щоб уникнути цього.)

І часто ви можете уникнути проблеми та покращити чіткість, трохи переставивши код. Наприклад, а не:

if (!cond) {
    do_this();
}
else {
    do_that();
}

Ви можете написати:

if (cond) {
     do_that();
}
else {
    do_this();
}

Це не завжди краще, але не завадить шукати можливості там, де він є.

Короткий зміст: У C та C ++ рівність порівнює trueта falseє небезпечним, надмірно багатослівним та поганим стилем. У багатьох інших мовах подібні порівняння можуть не бути небезпечними, але вони все ще надмірно багатослівні та поганий.


+1 - це одна відповідь із фактичним корисним технічним поясненням.
Майк Накіс

Я все ще думаю, що таким чином, незалежно від мови програмування, я завжди вважаю == trueце небезпечним. Так почувається краще.
Дерваль

1
@Dervall: припускати щось, що просто не так, це також не добре. У деяких мовах є декілька випадків, коли порівняння булевих рівностей є не тільки безпечним, але й фактично доречним, наприклад, у Haskell, яка має потужну систему неявного відключення без двонаправленого типу, можна написати, (==True) . fщоб уточнити, що ми хочемо -> Boolобґрунтування повернення-поліморфної функції f. Це чіткіше not . not . fі менш незручно, ніж (f :: a -> Bool).
Ліворуч близько

Також, безумовно, доречно робити такі речі, як pred(x)==pred(y)для функції повернення bool pred. Альтернатива, pred(x)? pred(y) : !pred(y)якою Ви погодитесь, навряд чи прийнятна.
Ліворуч близько

1
@leftaroundabout: Це добре, якщо ви знаєте це pred(x)і pred(y)використовуєте те саме значення для позначення істини, що є безпечним припущенням в деяких мовах, а не в інших. Наприклад, в C ви можете написати !!pred(x) == !!pred(y).
Кіт Томпсон,

14

Ці два функціонально однакові, тож який з них використовувати - це питання смаку.

Основна причина, яку я використовую, == falseполягає в тому, що я виявив, що !занадто просто не помітити, переглядаючи код.

Будучи сильно укушеним цим, я звик робити це чітко, коли тестувати на помилкове.


Якби оператор був названий так, notяк у Паскалі, я не думаю, що це стало б проблемою.


5
Саме тому проект C ++, над яким я працював над деяким програмним забезпеченням медичного обладнання, мав стандарт кодування, який мав намір == falseзамість !цієї ж причини (щоб він виділявся). Однак вимоги до використання не було == true, тому будь-яке ненульове значення все ще працювало як слід.
tcrosley

12
Я завжди вважав цей аргумент непереконливим - в C / C ++ / C # / Java / тощо є інші місця, де невідповідність одного символу має однаково значний вплив на інтерпретацію коду; виділення "!" як єдиний поганий для мене сенс не має.
Беван

5
@bevan Мабуть, вас ще не покусали.

1
Хоча я погоджуюся, що недогляд !- це, мабуть, найбільш клопітна помилка такого роду, це не повинно створювати звичку писати, ==falseа писати кращі одиничні тести.
Лише приблизно

8
@ ThorbjørnRavnAndersen Зовсім навпаки - мене протягом багатьох років кусали досить, що я навчив себе читати кожного персонажа . Я не автор всього (або навіть більшості) коду, який я маю читати щодня, тому будь-яка особиста умова, коли ми тут обговорюємо, має мінімальне значення: мені потрібно правильно зрозуміти весь код, який я читаю, а не просто речі, які я написав.
Беван

13

Якщо для вас condition == falseце справді "набагато природніше англійської мови", то я мушу припустити, що ви не є носієм мови. Інакше я не можу пояснити це, тому що ніхто не говорить так:

Якщо сонечко світить помилково, я залишаюся вдома.

Порівняйте це з

Якщо сонце не світить, я залишаюся вдома.

З цього приводу я погоджуюся, що єдиний стрункий !персонаж легко не помічається в коді. З цієї причини я віддаю перевагу ключовому слову, notколи його підтримує мова. Наприклад, це дозволяє C ++, хоча багато програмістів цього не знають.

Для мов, які потребують !, я розміщую пробіл між оператором і операндом. Це значно заважає заперечувати заперечення:

if (! condition) { … }

Зауважте, що кожен програміст повинен автоматично , без другої думки, перекладати це "не умовою". Досягнення такого роду вільне володіння ідіомами читання коду є одним з перших кроків у стані хорошого програміста.


7

Коли я бачу , var == falseя завжди задаюся питанням, є чи varце логічне або логічного типу з більш ніж двома значеннями (з, наприклад, maybeі undefined, а також trueі false, або що - щось на зразок дев'яти значень IEEE 1164 ).


8
3-е значення, як правило, "Файл не знайдено". thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx
Groky

6

тому що іноді ви можете писати boolean = false(з очевидними помилками) і false == booleanне здається природним (як би хороша практика не була)


Давним-давно, коли я вперше почав програмувати, ментовий наставник запропонував мені звикнути if( INVALID_HANDLE_VALUE == hFile )уникати подібних речей. Таким чином, якщо ви підсунете і використаєте один знак рівності замість двох, ви отримаєте помилку компілятора. Очевидно, це працює лише тоді, коли лівий вираз є постійною, але це врятувало мені більше болів у голові, ніж я можу порахувати.
Дрю Чапін

якщо ви використовуєте інструмент статичного аналізу, це допоможе вам заощадити в сто разів більше головних болів, і ви зможете відновити hFile==INVALID_HANDLE_VALUE написання природи .
Gqqnbig

4

if (!boolean_variable)перекладається на if the condition is not true.

if (boolean == false)перекладається на if the condition not false is true. Оскільки це перевернута логіка, це важче зрозуміти.


3
! істина означає неправда. Булева означає або неправдиву, або неправдиву, залежно від значення булевого значення, що саме є логічною інверсією.
S.Robins

1
@ S.Robins Я знаходжу дурну назву булевої для булевої змінної. Щось подібне, наприклад, isVisibleбуло б кращим прикладом. Тоді if (!isVisible)це означатиме, якщо не видно - що простіше зрозуміти тоді if (isVisible==false), що є зворотною логікою. Сподіваюся, зараз зрозуміліше. Або я неправильно зрозумів ваш коментар?
BЈович

2

У (набагато) старших компіляторах я вважаю, що вони би розбили (boolean == false) на 2 регістрові завдання та порівняти код машинною мовою. Перший приклад буде розбитий на одне завдання та оператора NOT. З точки зору продуктивності операція порівняння зайняла б декілька тактових циклів, залежно від розміру реєстру, який порівнюється, порівняно з побітною інверсією (1 тактова частота) і буде повільніше виконуватись.

Зважаючи на це, я вважаю, що новіші компілятори від цього відмовляються, тож слід нормально йти і з одним.


Генерування машинного коду - це завдання компілятора, а не мова програміста високого рівня ...
CVn

З історичних причин це, можливо, є однією з причин, коли один метод став кращим перед іншим.
Леголас

1

На роботі я часто маю справу з булевими, які можуть бути нульовими, тому я часто кодую цей випадок

if (value != null && value == true){
    //do something
}

тому що я особисто відчуваю, що симетрія полегшує читання. Особливо, якщо є й інші булеві тести.

Мені дуже не байдуже так чи інакше.


4
якщо value == trueтоді немає підстав перевіряти, чи не є це недійсним. Якщо value == nullвоно ніколи не повинно викликати оператор if, в першу чергу, то його if (value)повинно бути достатньо.
zzzzBov

1
Булеви - це об'єкти (у java), і тому вони можуть бути нульовими, тому просто кажучи - if (value)це виняток. Буду вдячний, якщо люди, які звертаються з головою, дають причину.
WuHoUnited

3
Я просто трапляюсь бачити це, не зволікаю. Булева нуль не є хорошою практикою. Чому? тому що булевий зазвичай представляє стан чогось увімкнено. У більшості випадків ви хочете оголосити його помилковим на початку, а потім змінити його разом із поведінкою. Дуже рідко бачити булеві не ініціалізовані.
Баклажан

Я маю згоду з баклажаном тут, я сам потрапив у шкідливу звичку (особливо на Яві) залишати неініціалізовані булі, а потім закінчувати перевірку на нуль. Я думаю, що це скоріше недолік мови, однак який накладає цю ваду на користувача. При оголошенні нової змінної bool, на мою думку, слід встановити значення false без ініціалізації.

2
@WuHoUnited, навіть якщо значення було недійсним, value == trueбуло б достатньо.
zzzzBov

1

Коли ви тестуєте справжню умову, це має сенс робити просто if (condition), особливо коли ви застосовуєте умову про іменування булевих змінних, що починається з "є": if (isOpen)цілком зрозуміло, і використання != falseбуде зайвим.

Для C / C ++ / Java / тощо. програміст, значення '!' Оператор повністю асимільований, до того, що ми автоматично маємо «не» у своїй свідомості, коли бачимо це. Тому мати так if (!isOpen)само ясно, як і if (_NOT_ isOpen)для мене. Але ви недостатньо знайомі, в C / C ++ ви можете створити макрос #define _NOT_ !. Але повірте, через кілька років це зовсім непотрібно.

Крім того, завжди бажано перевіряти булеві значення, не порівнюючи їх з буквальними. Наприклад, тестувати небезпечно, if (x == true)оскільки булеве значення вважається істинним, якщо воно не дорівнює нулю, а буквальне істинне має лише одне конкретне значення, тому x може бути 'true' (тобто ненульовим), і все ж порівняння оцінюватиметься як false (тому що це містить 2, а буквальна правда - це, скажімо, 1.) Звичайно, це не стосується порівняння з помилковим, але якщо ви не використовуєте його при тестуванні на істинність, навіщо використовувати його при тестуванні на помилкове?


Не потрібно робити макрос C ++, який ви пропонуєте, оскільки C ++ вже розуміє "не". Пов'язаний: stackoverflow.com/questions/2393673/c-and-or-not-xor-keywords
frozenkoi

Це правда, але це ключове слово лише для стандарту C ++ 0X. До цього це був просто ще один макрос.
Фабіо Чеконелло,

0

Розмір має значення ;)

У змішаних виразах легше читати:

boolean1 = false
boolean2 = true

p ! boolean1 and ! boolean2
p boolean1 == false and boolean2 == false

І особливо для прикладу рубіну, коли це велика різниця:

boolean = nil
p ! boolean         #-> true
p boolean == false  #-> false

нуль не є хибним, але це також неправда.


0

Виходячи з мого досвіду та відповідей з мого запитання, з яким ви зв’язалися.

Деякі люди вважають за краще використовувати if (умова), тому що одна вона коротше писати. і для мене це насправді має сенс, наприклад (! isValidated ()) я читаю це як Не підтверджене. але для мене це все ґрунтується на особистих уподобаннях, і це залежить від логічної структури методу isValidated (), якщо він повертає істину чи хибність



0

Для деяких людей, чим раніше буде виражений сенс, тим краще.

Тим людям, які мають "якщо! ..." порівняно швидше з "якщо ...", то потрібно перечитати всю умову (яка насправді може бути досить довгою, наприклад (thisThing = thatThing або щось = інше) АБО ( thinga = thingb і thinga = thingd) і т. д.) лише щоб знайти наприкінці == false.

Маючи! (Я фактично віддаю перевагу не тоді, коли мова дозволяє це) прямо напроти отримує англійську "не" для цієї умови раніше.

Це питання також призводить до розгляду щодо використання untilв мовах, які його підтримують, наприклад, робити "загальні речі", поки річ не завершиться. Як кажуть інші, мета вираження природної мови. Мені подобається приклад "світить сонце" вище.


0

Ще одна причина полягає в тому, що якщо ви працюєте в кодовій базі, яка використовує кілька мов, якщо є один ідіоматичний спосіб зробити те, що безпечно для всіх мов, це дуже гарна ідея зробити це так скрізь, щоб сформувати гарну звичку і рідше вони подорожують.

Я не можу придумати ніде, що if (!variable)(або його еквіваленти, такі як if not variableзалежно від вашої мови) не є безпечним, тоді як, наприклад if self.is_ready() == False: ..., не є безпечним у python, якщо self.is_ready()повернеться None, зараз чи в майбутньому, що було б абсолютно розумною справою для цього вкажіть, що вона не готова, оскільки так Noneсамо, як і фальси False.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.