Pourquoi utiliser! Boolean_variable sur boolean_variable == false

60

Un commentaire sur cette question: Vérifier si une méthode retourne false: assigne le résultat à une variable temporaire ou placez-vous une invocation de méthode directement au conditionnel? indique que vous devez utiliser !booleanau lieu de boolean == falselorsque les conditions de test. Pourquoi? Pour moi, boolean == falsec'est beaucoup plus naturel en anglais et c'est plus explicite. Je m'excuse s'il ne s'agit que d'une question de style, mais je me demandais s'il y avait une autre raison à cette préférence de !boolean?

ell
la source
28
C'est plus court pour écrire.
Zenon
39
C'est comme faire boolean == true: ça n'a pas de sens. Les expressions à l'intérieur des ifinstructions ne sont que cela: des expressions. Si quelque chose correspond déjà à une expression booléenne, pourquoi voudriez-vous ajouter un contrôle pour le forcer à évaluer?
Maxpm
10
@zzzzBov: Euh, non. Ce n'est pas ainsi que la plupart des programmeurs (de style C) le font.
Amara
9
@zzzzBov: Votre commentaire est ambigu. Si vous voulez dire que !boolean_variablec'est la façon dont la plupart des programmeurs C le font, je suis d'accord.
Keith Thompson
29
Et plus important encore, comment se fait-il que personne ne veuille écrire boolean != true?

Réponses:

153

Quand je vois une ligne comme celle-ci if (!lateForMeeting()), je lis que "Si pas en retard pour une réunion" , ce qui est assez simple à comprendre, par opposition à if (lateForMeeting() == false)ce que je lisais comme "Si le fait que je sois en retard pour une réunion soit faux " .

Leur sens est identique, mais le premier est plus proche de la façon dont la phrase anglaise équivalente serait construite.

kba
la source
27
+1 En Python, vous écrivez réellement if not late_for_meeting:)
phunehehe
42
Je soutiens que si "si ___ est faux" sonne plus naturel que "si pas ___", le nom de ___ doit être amélioré.
Mike DeSimone
12
En Perl, vous pouvez écrireunless late_for_meeting
Henrik Ripa
4
@HenrikRipa: Il semble que presque tout ce que vous pouvez taper est un code légal en Perl. Que ce soit ou non ce que vous voulez est une autre question;)
Adam Robinson
4
@ A-Cube, je n'aurais pas une méthode comme celle-là pour commencer. Au lieu de cela, j'aurais une méthode appelée done(). Les doubles négatifs sont mauvais.
kba
97

Ecrire == falseet == trueest redondant. Cela peut aussi être pris à des extrêmes arbitraires. Si vous commencez à écrire

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

Alors pourquoi pas

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

Ou pourquoi pas

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

La morale de cette histoire est que si conditionest une expression booléenne, vous n'avez pas besoin d'ajouter == false; c'est à cela que !sert l' opérateur ;)

Andres F.
la source
Je n'ai pas pensé à ça!
ell
51
== falsen'est PAS redondant, mais plus verbeux que !. OTOH, == trueest redondant.
dan04
4
@ dan04 Vous avez raison. Cependant, dans le sens que je voulais dire, cela reste une mauvaise idée. Considérez (exp1 != exp2)vs ((exp1 == exp2) == false). Certes, ce sont des scénarios artificiels, mais vous ne devriez presque jamais écrire de comparaisons explicites entre vrai et faux. Tout comme vous devriez utiliser opérateur !=, vous devriez donc utiliser !.
Andres F.
26
@ dan04: Il est redondant lorsque la langue est déjà proposée !.
DeadMG
5
@ dan04: Chaque fois que vous écrivez bool_expression == bool_literal, le == ...est redondant. Que vous testiez vrai ou faux n’a aucune importance. C'est juste un changement dans l'ordre des blocs conséquents / alternatifs. Les exemples d'Andres illustrent parfaitement ce point. La plupart des compilateurs modernes optimiseront la redondance, mais elle reste redondante.
Lèse majesté
70

En C et certaines langues similaires, en comparant les expressions booléennes pour l' égalité à falseou trueest une habitude dangereuse.

En C, toute expression scalaire (numérique ou pointeur) peut être utilisée dans un contexte booléen, par exemple en tant que condition d'une ifinstruction. La règle C if (cond)est équivalente à if (cond != 0)- c’est- à -dire que zéro est faux et que toute valeur autre que zéro est vraie. Si condest de type pointeur, 0est traitée comme une constante de pointeur nulle. if (ptr)des moyens if (ptr != NULL).

Cela signifie que

if (cond)

et

if (cond == true)

ne veut pas dire la même chose . Le premier est vrai si condest non nul; la seconde n'est vraie que si elle est égale à true, ce qui en C (si vous avez #include <stdbool.h>) est simplement 1.

Par exemple, la isdigit()fonction déclarée dans <ctype.h>renvoie une intvaleur, 0si l'argument est un chiffre, différent de zéro s'il ne l'est pas. Il peut revenir 42pour indiquer que la condition est vraie. La comparaison 42 == trueéchouera.

Il se trouve que 0c'est la seule valeur considérée comme fausse, alors la comparaison pour l'égalité falsefonctionnera; if (!cond)et if (cond == false)faire la même chose. Mais si vous voulez en tirer parti, vous devez vous rappeler que comparer à falseest correct, et que comparer truene l’est pas. Pire encore, comparer à truefonctionnera la plupart du temps (par exemple, les opérateurs d'égalité et relationnels donnent toujours un 0ou 1). Cela signifie que tous les bogues que vous introduisez en utilisant ceci pourraient être difficiles à localiser. (Ne vous inquiétez pas, ils apparaîtront dès que vous aurez présenté le code à un client important.)

C ++ a des règles légèrement différentes. par exemple, son booltype est un peu plus étroitement intégré dans le langage et est if (cond)converti conden dactylographie bool. Mais l'effet est (principalement) le même.

Certaines autres langues ont ce que l’on pourrait appeler des booléens plus sages, tels que cond == trueet cond == false(ou quelle que soit la syntaxe qui s’avère) est sans danger. Malgré tout, chaque langue que j'ai vue a un opérateur notou !; c'est là, alors vous pourriez aussi bien l'utiliser. Utiliser cond == falseplutôt que !condou not condn'améliore pas, à mon avis, la lisibilité. (Il est vrai que le !personnage peut être difficile à voir d'un coup d'œil; j'ajoute parfois un espace après le !pour l'éviter.)

Et souvent, vous pouvez éviter le problème et améliorer la clarté en réorganisant légèrement le code. Par exemple, plutôt que:

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

vous pourriez écrire:

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

Ce n'est pas toujours mieux, mais il n'y a pas de mal à chercher des opportunités là où elles se trouvent.

Résumé: En C et C ++, les comparaisons d'égalité à trueet falsesont dangereux, trop bavard, et le style pauvre. Dans de nombreuses autres langues, de telles comparaisons ne sont peut-être pas dangereuses, mais elles sont toujours trop verbeuses et d'un style médiocre.

Keith Thompson
la source
+1 pour cela étant la réponse unique avec l'explication technique réellement utile.
Mike Nakis
Je pense toujours de cette façon, peu importe le langage de programmation, je suppose toujours que == truec'est dangereux. Je me sens mieux comme ça.
Dervall
1
@Dervall: supposer que quelque chose n'est tout simplement pas le cas n'est pas bon non plus. Il existe quelques cas particuliers dans certaines langues où la comparaison d’égalité de booléens est non seulement sûre mais en fait appropriée, par exemple en Haskell, qui possède un système de type fort sans implicitement diffusé avec inférence de type bidirectionnel, on pourrait écrire (==True) . fpour préciser que nous voulons l' -> Boolinstanciation de la fonction polymorphe de retour f. C'est plus clair que not . not . fet moins gênant que (f :: a -> Bool).
gauche du
En outre, il est certainement approprié de faire des choses comme pred(x)==pred(y)pour une fonction de retour de bool pred. L'alternative serait pred(x)? pred(y) : !pred(y)que vous conviendrez, c'est difficilement acceptable.
gauche du
1
@leftaroundabout: C'est bien si vous le savez pred(x)et pred(y)utilisez la même valeur pour indiquer la vérité, ce qui est une hypothèse sûre dans certaines langues mais pas dans d'autres. En C, par exemple, vous pourriez écrire !!pred(x) == !!pred(y).
Keith Thompson
14

Les deux sont fonctionnellement identiques, donc utiliser est une question de goût.

La principale raison pour laquelle je l' utilise == falseest que j'ai trouvé que !trop facile d'oublier, quand on regarde le code.

Ayant été sévèrement mordu par cela, j'ai pris l'habitude de le préciser très clairement lorsque je teste faux.


Si l'opérateur avait été nommé noten Pascal, je ne pense pas que cela serait devenu un problème.

utilisateur1249
la source
5
Pour cette raison même, un projet C ++ sur lequel je travaillais pour un logiciel de dispositif médical avait une norme de codage qui l’était == falseau lieu de !pour la même raison (pour le faire ressortir). Cependant, il n’existait aucune obligation d’utilisation == true, de sorte que toute valeur autre que zéro fonctionnait toujours comme il se doit.
Tcrosley
12
J'ai toujours trouvé cet argument peu convaincant - il existe d'autres endroits en C / C ++ / C # / Java / etc. où l'absence de voir un seul caractère a un impact significatif similaire sur l'interprétation du code; singulariser "!" comme le seul mauvais n'a pas de sens pour moi.
Bevan
5
@bevan Apparemment, vous n'avez pas encore été mordu.
1
Bien que je convienne que l’oubli !est probablement l’erreur la plus gênante de ce type, mais cela devrait inciter l’OMI à ne pas avoir l’habitude de prendre l’écriture ==falsemais de mieux écrire les tests unitaires.
gauche du
8
@ ThorbjørnRavnAndersen Bien au contraire - j'ai été assez souvent mordu au fil des années pour apprendre à lire tous les personnages . Je ne suis pas l'auteur de tout (ou même de la plupart) du code que je dois lire au jour le jour. Toute convention personnelle dont nous discutons ici a une valeur minimale: je dois comprendre correctement tout le code que j'ai lu, et non tout ce que j'ai écrit.
Bevan
13

Si condition == falseest bien «beaucoup plus naturel en anglais» pour vous, alors je dois supposer que vous n’êtes pas un locuteur natif. Sinon, je ne peux pas expliquer cela, car personne ne parle comme ça:

Si le soleil brille est faux, je reste à la maison.

Comparez cela à

Si le soleil ne brille pas, je reste à la maison.

Cela dit, je conviens que le !code du caractère unique et élancé est facilement négligé. Pour cette raison, je préfère le mot clé notlorsqu'il est pris en charge par la langue. C ++ , par exemple , ne permet cela bien que beaucoup de programmeurs ne sont pas au courant.

Pour les langues qui nécessitent !, je mets un espace entre opérateur et opérande. Cela rend la négation beaucoup plus difficile à négliger:

if (! condition) { … }

Notez que chaque programmeur doit traduire cela automatiquement , sans y réfléchir à deux fois, afin de «ne pas conditionner» dans sa tête. L’acquisition de ce genre de maîtrise de la lecture d’idiomes de code fait partie des premières étapes pour devenir un bon programmeur.

Konrad Rudolph
la source
7

Quand je vois, var == falseje me demande toujours s'il vars'agit d'un booléen ou d'un type logique avec plus de deux valeurs (avec, par exemple, un maybeet un undefinedainsi que trueet false, ou quelque chose comme les neuf valeurs de IEEE 1164 ).

AProgrammer
la source
8
La 3ème valeur est généralement "Fichier non trouvé". thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx
Groky
6

parce que parfois vous pouvez écrire boolean = false(avec les erreurs évidentes) et false == booleanne semble pas naturel (peu importe la qualité de votre pratique)

monstre à cliquet
la source
Il y a longtemps, lorsque j'ai commencé à programmer, un de mes mentors m'a suggéré de prendre l'habitude de le faire if( INVALID_HANDLE_VALUE == hFile )pour éviter des situations de ce genre. Ainsi, si vous vous trompez et utilisez un signe égal au lieu de deux, vous obtiendrez une erreur du compilateur. Évidemment, cela ne fonctionne que lorsque l'expression de gauche est une constante, mais cela m'a évité plus de maux de tête que je ne peux en compter.
Drew Chapin
si vous utilisez un outil d'analyse statique, vous économiserez cent fois plus de maux de tête et vous pourrez restaurer l' hFile==INVALID_HANDLE_VALUE écriture naturelle .
Gqqnbig
4

if (!boolean_variable)se traduit par if the condition is not true.

if (boolean == false)se traduit par if the condition not false is true. Parce que c'est une logique inversée, il est plus difficile de comprendre.

BЈовић
la source
3
! vrai ne veut pas dire vrai. ! boolean signifie soit pas faux, soit pas vrai en fonction de la valeur du booléen, qui est elle-même une inversion logique.
S.Robins
1
@ S.Robins Je trouve un nom stupide de booléen pour une variable booléenne. Quelque chose comme par exemple isVisibleserait un meilleur exemple. Alors if (!isVisible)voudrait dire si non visible - ce qui est plus simple à comprendre alors if (isVisible==false), qui est une logique inverse. J'espère que c'est plus clair maintenant. Ou ai-je mal compris votre commentaire?
BЈовић
2

Dans les compilateurs (beaucoup) plus anciens, je pense qu'ils diviseraient (boolean == false) en 2 assignations de registre et un code de comparaison en langage machine. Le premier exemple serait divisé en une affectation et un opérateur NOT. En termes de performances, l'opération de comparaison prendrait plusieurs cycles d'horloge, en fonction de la taille du registre comparé, par rapport à une inversion au niveau du bit (1 horloge) et serait plus lente à exécuter.

Cela étant dit, je pense que les nouveaux compilateurs l’abandonnent, ce qui devrait être acceptable.

enflammer
la source
Générer du code machine, c'est le travail du compilateur, pas celui du programmeur de langage de haut niveau ...
a CVn le
Pour des raisons historiques, cela peut très bien être l’une des raisons pour lesquelles une méthode est devenue préférée par rapport à l’autre.
Legolas
1

Au travail, j’ai souvent affaire à des booléens qui peuvent être nuls alors je vais souvent coder ce cas comme suit:

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

parce que je pense personnellement que la symétrie facilite la lecture. Surtout s'il y a d'autres booléens testés.

Je ne me soucie pas vraiment d'une manière ou d'une autre.

WuHoUnited
la source
4
si value == truealors il n'y a aucune raison de vérifier que ce n'est pas nul. Si value == nullcela ne devrait jamais déclencher la déclaration if en premier lieu, cela if (value)devrait être suffisant.
zzzzBov
1
Les booléens sont des objets (en java) et peuvent donc être nuls. Il suffit de dire que if (value)lève une exception. J'apprécierais que les gens qui votent par la négative donnent une raison.
WuHoUnited
3
Il se trouve que je vois cela, mais je n’ai pas eu de vote vers le bas. Boolean null n'est pas une bonne pratique. Pourquoi? parce que booléen représente généralement un état d'activation ou de désactivation. Dans la plupart des cas, vous voudrez le déclarer faux au début, puis le changer en même temps que le comportement. Il est très rare de voir un booléen ne pas être initialisé.
Aubergine
Je suis d’accord avec Aubergine, je suis moi-même tombé dans la mauvaise habitude (en particulier à Java) de laisser les booléens non initialisés, puis de vérifier null. Je pense que ceci est plus un défaut de la langue, cependant, qui impose ce défaut à l'utilisateur. Lors de la déclaration d'une nouvelle variable bool, la valeur par défaut devrait être false sans initialisation à mon avis.
2
@WuHoUnited, même si la valeur était null, value == trueserait suffisant.
zzzzBov
1

Lorsque vous testez la condition vraie, il est logique de le faire if (condition), en particulier lorsque vous appliquez la convention de nommage des variables booléennes commençant par «is»: if (isOpen)est parfaitement claire et l'utilisation != falseserait redondante.

Pour un C / C ++ / Java / etc. programmeur, le sens du '!' l’opérateur est complètement assimilé, au point que nous n’avons automatiquement «pas» en tête lorsque nous le voyons. Donc, avoir if (!isOpen)est aussi clair que if (_NOT_ isOpen)pour moi. Mais vous n'êtes pas assez familier. En C / C ++, vous pouvez créer une macro avec #define _NOT_ !. Mais croyez-moi, après quelques années, c'est complètement inutile.

De plus, il est toujours préférable de tester les valeurs booléennes sans les comparer avec les littéraux. Par exemple, il est dangereux de tester, if (x == true)car une valeur booléenne est considérée comme vraie si elle n’est pas nulle et que le vrai littéral n’a qu’une valeur spécifique. X peut donc être 'vrai' (c'est-à-dire différent de zéro) et la comparaison doit être évaluée à faux (car contient 2 et le vrai est littéralement, disons 1.) Bien sûr, cela ne s'applique pas à une comparaison avec false, mais si vous ne l'utilisez pas lors du test de true, pourquoi l'utiliser lors du test de false?

Fabio Ceconello
la source
Il n'est pas nécessaire de créer la macro C ++ que vous proposez, car C ++ comprend déjà «non». Connexes: stackoverflow.com/questions/2393673/c-and-or-not-xor-keywords
frozenkoi
C'est vrai, mais c'est un mot clé pour la norme C ++ 0X uniquement. Avant cela, c'était juste une autre macro.
Fabio Ceconello
0

Questions de taille ;)

En expressions mixtes, il est plus facile de lire:

boolean1 = false
boolean2 = true

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

Et surtout pour Ruby un exemple où il y a une grande différence:

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

nil n'est pas faux, mais ce n'est pas vrai non plus.

noué
la source
0

Basé sur mon expérience et les réponses de ma question que vous avez liées.

Certaines personnes préfèrent utiliser si (condition), car il est plus court à écrire. et pour moi, cela a du sens, par exemple (! isValidated ()) Je lis ceci comme étant non validé. mais pour moi tout est basé sur les préférences personnelles, et cela dépend de la structure logique de la méthode isValidated (), si elle retourne true ou false

KyelJmD
la source
0

Si vous avez nommé votre variable correctement, alors !booleanc'est plus naturel. Cela se lit comme not booleann'importe qui qui est assez d'un programmeur pour lire le code mentalement.

Courses de légèreté avec Monica
la source
0

Pour certaines personnes, plus tôt un sens est exprimé, mieux c'est.

Pour ceux qui ont "if! ..." se compare plus rapidement à "if ...", alors il faut lire toute la condition (ce qui pourrait en fait être assez long, par exemple (thisThing = thatThing ou quelque chose = autre chose) OU ( thinga = thingb et thinga = thingd), etc.) juste pour trouver le == faux à la fin.

Avoir le! (Je préfère en fait un pas quand la langue le permet) dès le début obtient l'anglais 'not' pour cette condition plus tôt.

Ce problème conduit également à envisager l’utilisation untildans les langues qui le supportent, par exemple, faire des «choses courantes» jusqu’à ce que tout soit terminé. Comme d’autres le disent, l’objectif est l’expression dans le langage naturel. J'aime l'exemple du "soleil brille" ci-dessus.

rebut
la source
0

Une autre raison est que si vous travaillez dans une base de code qui utilise plusieurs langues, s'il existe un moyen idiomatique de faire quelque chose de sûr dans toutes les langues, c'est une très bonne idée de le faire partout pour que vous ayez une bonne habitude. et sont moins susceptibles de trébucher.

Je ne peux penser à aucun endroit où if (!variable)(ou des équivalents tels que if not variableselon votre langue) n'est pas sûr, alors que par exemple, il if self.is_ready() == False: ...n'est pas sûr en python s'il self.is_ready()retourne None, maintenant ou à l'avenir, ce qui serait une chose tout à fait raisonnable à faire pour indique qu'il n'était pas prêt car Noneest aussi semblable à falsey False.

daphtdazz
la source