¿Por qué usar! Boolean_variable sobre boolean_variable == false


60

Un comentario sobre esta pregunta: ¿ Comprobar si un método devuelve falso: asignar el resultado a la variable temporal o poner la invocación del método directamente en condicional? dice que debe usar en !booleanlugar de boolean == falsecuando prueba las condiciones. ¿Por qué? Para mí boolean == falsees mucho más natural en inglés y es más explícito. Me disculpo si esto es solo una cuestión de estilo, pero me preguntaba si había alguna otra razón para esta preferencia !boolean.


28
Es más corto de escribir.
Zenon

39
Es como hacerlo boolean == true: no tiene sentido. Las expresiones dentro de las ifdeclaraciones son solo eso: expresiones. Si algo ya se evalúa como una expresión booleana, ¿por qué agregaría un cheque para obligarlo a evaluar?
Maxpm

10
@zzzzBov: Um, no. Así no es como lo hacen la mayoría de los programadores (estilo C).
amara

99
@zzzzBov: Tu comentario es ambiguo. Si quisiste decir que !boolean_variablees la forma en que la mayoría de los programadores de C lo hacen, estoy de acuerdo.
Keith Thompson

29
Y lo más importante, ¿cómo es que nadie quiere escribir boolean != true?

Respuestas:


153

Cuando veo una línea como if (!lateForMeeting()), leí eso como "Si no es tarde para reunirse" , lo cual es bastante sencillo de entender, en lugar de if (lateForMeeting() == false)lo que leería como "Si el hecho de que llegue tarde a la reunión es falso " .

Tienen un significado idéntico, pero el primero está más cerca de cómo se construiría la oración equivalente en inglés.


27
+1 En Python realmente escribes if not late_for_meeting:)
phunehehe

42
Sostengo que si "si ___ es falso" suena más natural que "si no ___", entonces el nombre de ___ necesita mejorar.
Mike DeSimone

12
En Perl puedes escribirunless late_for_meeting
Henrik Ripa

44
@HenrikRipa: Parece que casi todo lo que puedes escribir es código legal en Perl. Si hace o no lo que quieres es otra pregunta;)
Adam Robinson

44
@ A-Cube No tendría un método como ese para empezar. En cambio, tendría un método llamado done(). Los negativos dobles son malos.
kba

97

Escritura == falsey == truees redundante. También se puede llevar a extremos arbitrarios. Si empiezas a escribir

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

Entonces porque no

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

O porque no

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

La moraleja de esta historia es que si conditiones una expresión booleana, entonces no necesita agregar == false; para eso está el operador !;)


¡No pensé en esto!
ell

51
== falseNO es redundante, solo más detallado que !. OTOH, == truees redundante.
dan04

44
@ dan04 Tienes razón. Sin embargo, en el sentido en que lo dije en serio, sigue siendo una mala idea. Considere (exp1 != exp2)vs ((exp1 == exp2) == false). Es cierto que estos son escenarios inventados, pero aún así casi nunca debes escribir comparaciones explícitas con verdadero o falso. Del mismo modo que debe usar el operador !=, también debe usarlo !.
Andres F.

26
@ dan04: es redundante cuando el idioma ya ofrece !.
DeadMG

55
@ dan04: cada vez que escribes bool_expression == bool_literal, == ...es redundante. Si está probando verdadero o falso es irrelevante. Es solo un cambio en el orden de los bloques consecuentes / alternativos. Los ejemplos de Andrés ilustran este punto perfectamente. La mayoría de los compiladores modernos optimizarán la redundancia, pero sigue siendo redundante.
Lèse majesté

70

En C y algunos lenguajes similares, comparar expresiones booleanas para igualdad falseo truees un hábito peligroso.

En C, cualquier expresión escalar (numérica o puntero) se puede utilizar en un contexto booleano, por ejemplo, como la condición de una ifdeclaración. La regla C if (cond)es equivalente a if (cond != 0), es decir, cero es falso y cualquier valor distinto de cero es verdadero. Si condes de tipo puntero, 0se trata como una constante de puntero nulo; if (ptr)significa if (ptr != NULL).

Esto significa que

if (cond)

y

if (cond == true)

No significan lo mismo . El primero es verdadero si condno es cero; el segundo es verdadero solo si es igual a true, que en C (si tiene #include <stdbool.h>) es simplemente 1.

Por ejemplo, la isdigit()función declarada en <ctype.h>devuelve un intvalor, 0si el argumento es un dígito, no cero si no lo es. Puede volver 42para indicar que la condición es verdadera. La comparación 42 == truefallará.

Sucede que ese 0es el único valor considerado falso, por lo que la comparación para igualdad falsefuncionará; if (!cond)y if (cond == false)hacer lo mismo Pero si vas a aprovechar eso, debes recordar que comparar con falseestá bien, y comparar con trueno lo está. Peor aún, la comparación con truefuncionará la mayor parte del tiempo (por ejemplo, los operadores de igualdad y relacionales siempre rinden 0o 1). Esto significa que cualquier error que introduzca al usar esto aún podría ser difícil de rastrear. (No se preocupe, aparecerán tan pronto como demuestre el código a un cliente importante).

C ++ tiene reglas ligeramente diferentes; por ejemplo, su booltipo está un poco más integrado en el lenguaje y se if (cond)convierte conden tipo bool. Pero el efecto es (principalmente) el mismo.

Algunos otros idiomas tienen lo que uno podría llamar booleanos con mejor comportamiento, de modo que cond == truey cond == false(o lo que sea que sea la sintaxis) es seguro. Aun así, cada idioma que he visto tiene un operador notu !; está ahí, así que bien podrías usarlo. Usar en cond == falselugar de !condo not condno, en mi opinión, mejora la legibilidad. (Es cierto que el !personaje puede ser difícil de ver de un vistazo; a veces agrego un espacio después !para evitar esto).

Y a menudo puede evitar el problema y mejorar la claridad reorganizando ligeramente el código. Por ejemplo, en lugar de:

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

podrías escribir:

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

Eso no siempre es mejor, pero no está de más buscar oportunidades donde está.

Resumen: en C y C ++, las comparaciones de igualdad con truey falseson peligrosas, excesivamente detalladas y con un estilo pobre. En muchos otros idiomas, tales comparaciones pueden no ser peligrosas, pero siguen siendo demasiado detalladas y de mal estilo.


+1 porque esta es la única respuesta con la explicación técnica útil real.
Mike Nakis

Todavía pienso de esta manera, independientemente del lenguaje de programación, siempre asumo que == trueno es seguro. Se siente mejor así.
Dervall

1
@Dervall: asumir algo que simplemente no es el caso tampoco es bueno. Hay algunos casos de esquina en ciertos idiomas en los que la comparación de igualdad de los booleanos no solo es segura sino que, de hecho, es apropiada, por ejemplo en Haskell, que tiene un sistema de tipo fuerte implícito sin conversión con inferencia de tipo bidireccional, se podría escribir (==True) . fpara aclarar que queremos la -> Boolinstanciación de la función de retorno polimórfico f. Eso es más claro not . not . fy menos incómodo que (f :: a -> Bool).
Leftaroundabout

Además, ciertamente es apropiado hacer cosas como pred(x)==pred(y)una función de retorno de bool pred. La alternativa sería pred(x)? pred(y) : !pred(y)que estarás de acuerdo es difícilmente aceptable.
Leftaroundabout

1
@leftaroundabout: Eso está bien si lo sabes pred(x)y pred(y)usas el mismo valor para denotar la verdad, lo cual es una suposición segura en algunos idiomas pero no en otros. En C, por ejemplo, podrías escribir !!pred(x) == !!pred(y).
Keith Thompson

14

Los dos son funcionalmente idénticos, por lo que cuál usar es cuestión de gustos.

La principal razón por la que yo utilizo == falsees que he encontrado que !es muy fácil pasar por alto, cuando se mira en código.

Después de haber sido mordido severamente por esto, me he acostumbrado a dejarlo muy claro cuando hago pruebas de falso.


Si el operador hubiera sido nombrado notcomo en Pascal, no creo que esto se hubiera convertido en un problema.


55
Por esta misma razón, un proyecto de C ++ en el que trabajé para algún software de dispositivo médico tenía un estándar de codificación obligatorio en == falselugar de !por esta misma razón (para que se destaque). Sin embargo, no había ningún requisito para usar == true, por lo que cualquier valor distinto de cero seguía funcionando como debería.
tcrosley

12
Este argumento siempre me ha parecido poco convincente: hay otros lugares en C / C ++ / C # / Java / etc. en los que no ver un solo carácter tiene un impacto igualmente significativo en la interpretación del código; singularizar "!" ya que el único malo no tiene sentido para mí.
Bevan

55
@bevan Aparentemente aún no te han mordido.

1
Si bien estoy de acuerdo en que pasar por alto !es probablemente el error más problemático de este tipo, esto en mi opinión no debería dar lugar a la costumbre de escribir ==falsesino de escribir mejores pruebas unitarias.
Leftaroundabout

8
@ ThorbjørnRavnAndersen Todo lo contrario: a lo largo de los años me han mordido con la suficiente frecuencia como para haberme enseñado a leer cada personaje . No soy el autor de todo (o incluso la mayoría) del código que tengo que leer día a día, por lo que cualquier convención personal que estamos discutiendo aquí tiene un valor mínimo: necesito entender correctamente todo el código que leo, no solo las cosas que he escrito.
Bevan

13

Si condition == falserealmente es "mucho más natural en inglés" para usted, entonces debo suponer que no es un hablante nativo. De lo contrario, no puedo explicar esto, porque nadie habla así:

Si el sol brilla es falso, me quedo en casa.

Compara eso con

Si el sol no brilla, me quedo en casa.

Dicho esto, estoy de acuerdo en que el carácter único y delgado !se pasa por alto fácilmente en el código. Por esa razón, prefiero la palabra clave notcuando es compatible con el idioma. C ++, por ejemplo , permite esto, aunque muchos programadores no lo saben.

Para los idiomas que requieren !, pongo un espacio entre el operador y el operando. Esto hace que la negación sea mucho más difícil de pasar por alto:

if (! condition) { … }

Tenga en cuenta que cada programador debe traducir esto automáticamente , sin pensarlo dos veces, a "no condicionar" en su cabeza. Adquirir este tipo de fluidez en la lectura de modismos de códigos es uno de los primeros pasos para convertirse en un buen programador.



6

porque a veces podrías escribir boolean = false(con los errores obvios) y false == booleanno parece natural (no importa cuán buena sea la práctica)


Hace mucho tiempo, cuando comencé a programar, un mentor mío me sugirió que me acostumbrara if( INVALID_HANDLE_VALUE == hFile )a evitar cosas como esas. De esa manera, si se resbala y usa un signo igual en lugar de dos, obtendrá un error de compilación. Obviamente, esto solo funciona cuando la expresión izquierda es una constante, pero me ha ahorrado más dolores de cabeza de los que puedo contar.
Drew Chapin

Si utiliza una herramienta de análisis estático, le ahorrará cientos de veces más dolores de cabeza y podrá restaurar la hFile==INVALID_HANDLE_VALUE escritura de la naturaleza .
Gqqnbig

4

if (!boolean_variable)se traduce en if the condition is not true.

if (boolean == false)se traduce en if the condition not false is true. Debido a que es una lógica inversa, es más difícil de entender.


3
! verdadero significa no cierto. ! booleano significa que no es falso o no es verdadero dependiendo del valor del booleano, que en sí mismo es una inversión lógica.
S.Robins

1
@ S.Robins Encuentro el estúpido nombre de booleano para una variable booleana. Algo así, por ejemplo isVisible, sería un mejor ejemplo. Entonces if (!isVisible)significaría si no es visible, lo cual es más fácil de entender entonces if (isVisible==false), que es una lógica inversa. Espero que sea más claro ahora. O, ¿entendí mal tu comentario?
B 26овић

2

En compiladores (mucho) más antiguos, creo que se dividirían (booleano == falso) en 2 asignaciones de registro y un código de comparación en lenguaje de máquina. El primer ejemplo se dividiría en una tarea y un operador NOT. En términos de rendimiento, la operación de comparación tomaría varios ciclos de reloj, dependiendo del tamaño del registro que se compara, en comparación con una inversión bit a bit (1 reloj) y sería más lenta de ejecutar.

Dicho esto, creo que los compiladores más nuevos eliminan esto, por lo que debería estar bien seguir con cualquiera.


Generar código de máquina es el trabajo del compilador, no el programador de lenguaje de alto nivel ...
un CVn

Por razones históricas, esta puede muy bien ser una de las razones por las que un método se convirtió en el preferido sobre el otro.
Legolas

1

En el trabajo, a menudo trato con booleanos que pueden ser nulos, así que a menudo codifico este caso como

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

porque personalmente siento que la simetría hace que sea más fácil de leer. Especialmente si también se están probando otros booleanos.

Realmente no me importa de una forma u otra.


44
si value == trueentonces no hay razón para verificar que no sea nulo. Si el value == nullnunca debe desencadenar la declaración if en primer lugar, entonces if (value)debería ser suficiente.
zzzzBov

1
Los booleanos son objetos (en Java) y, por lo tanto, pueden ser nulos, por lo que solo decir if (value)arroja una excepción. Agradecería que las personas que votan negativamente den una razón.
WuHoUnited

3
Por casualidad veo esto, no voté en contra. El booleano nulo no es una buena práctica. ¿Por qué? porque booleano generalmente representa un estado de algo encendido y apagado. En la mayoría de los casos, desearía declararlo falso al principio y luego cambiarlo junto con el comportamiento. Es muy raro ver que el booleano no se inicializa.
Berenjena

Tengo que estar de acuerdo con Aubergine aquí, yo mismo he caído en el mal hábito (especialmente en Java) de dejar los bools sin inicializar y luego terminar buscando nulos. Creo que esto es más una falla del lenguaje, sin embargo, lo que impone esa falla al usuario. Al declarar una nueva variable bool, en mi opinión, debería ser falsa sin inicialización.

2
@WuHoUnited, incluso si el valor fuera nulo, value == truesería suficiente.
zzzzBov

1

Cuando está probando la verdadera condición, tiene sentido hacerlo solo if (condition), especialmente cuando aplica la convención de nombrar variables booleanas que comienzan con 'es': if (isOpen)es perfectamente claro y su uso != falsesería redundante.

Para un C / C ++ / Java / etc. programador, el significado del '!' El operador está completamente asimilado, hasta el punto de que automáticamente tenemos "no" en nuestras mentes cuando lo vemos. Entonces tener if (!isOpen)es tan claro como if (_NOT_ isOpen)para mí. Pero no estás lo suficientemente familiarizado, en C / C ++ puedes crear una macro #define _NOT_ !. Pero confía en mí, después de unos años esto es completamente innecesario.

Aparte de eso, siempre es preferible probar valores booleanos sin compararlos con literales. Por ejemplo, es peligroso probar if (x == true)porque un valor booleano se considera verdadero si no es cero, y el verdadero literal tiene solo un valor específico, por lo que x podría ser 'verdadero' (es decir, distinto de cero) y aún así la comparación se evalúa como falsa (porque contiene 2 y el verdadero literal es, digamos, 1.) Por supuesto, eso no se aplica a una comparación con falso, pero si no lo usa cuando prueba verdadero, ¿por qué usarlo cuando prueba falso?


No es necesario hacer la macro de C ++ que propone, ya que C ++ ya entiende 'no'. Relacionado: stackoverflow.com/questions/2393673/c-and-or-not-xor-keywords
frozenkoi

Eso es cierto, pero es una palabra clave solo para el estándar C ++ 0X. Antes de eso, era solo otra macro.
Fabio Ceconello

0

El tamaño importa ;)

En expresiones mixtas es más fácil de leer:

boolean1 = false
boolean2 = true

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

Y especial para ruby ​​un ejemplo donde hay una gran diferencia:

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

nil no es falso, pero tampoco es cierto.


0

Basado en mi experiencia y las respuestas de mi búsqueda a la que te has vinculado.

Algunas personas prefieren usar if (condición), porque la razón es que es más corto de escribir. y para mí tiene sentido, por ejemplo (! isValidated ()) Leí esto como No validado. pero para mí todo se basa en preferencias personales, y depende de la estructura lógica del método isValidated (), si devuelve verdadero o falso


0

Si nombró su variable correctamente, entonces !booleanes más natural. Se lee como not booleana cualquiera que sea lo suficientemente programador como para leer código mentalmente.


0

Para algunas personas, cuanto antes se exprese un significado, mejor.

Para aquellas personas que tienen "if! ..." se compara más rápido con "if ..." y luego tienen que leer toda la condición (que en realidad podría ser bastante larga, por ejemplo (thisThing = thatThing o algo = la otra cosa) O ( thinga = thingb y thinga = thingd), etc.) solo para encontrar el == falso al final.

Tener el! (De hecho, prefiero un no cuando el idioma lo permite) de inmediato obtiene el inglés 'no' para esta condición allí antes.

Este problema también lleva a consideración para usarlo untilen los idiomas que lo admiten, por ejemplo, hacer "cosas comunes" hasta que se complete. Como otros dicen, el objetivo es la expresión en lenguaje natural. Me gusta el ejemplo de "el sol está brillando" arriba.


0

Otra razón es que si está trabajando en una base de código que usa varios idiomas, si hay una forma idiomática de hacer algo que sea seguro en todos los idiomas, es una buena idea hacerlo de esa manera en todas partes para formar un buen hábito y son menos propensos a tropezar.

No puedo pensar en ningún lugar que if (!variable)(o sus equivalentes, como if not variabledepender de su idioma) no sea seguro, mientras que, por ejemplo, if self.is_ready() == False: ...no es seguro en Python si self.is_ready()regresa None, ahora o en el futuro, lo que sería algo totalmente razonable que haga. indicar que no estaba listo ya que Nonees tan falso como False.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.