Por que usar! Boolean_variable Over boolean_variable == false

60

Um comentário sobre esta pergunta: Verificando se um método retorna false: atribua resultado à variável temporária ou coloque a invocação do método diretamente em condicional? diz que você deve usar em !booleanvez de boolean == falsetestar condições. Por quê? Para mim boolean == falseé muito mais natural em inglês e é mais explícito. Peço desculpas se isso é apenas uma questão de estilo, mas eu queria saber se havia algum outro motivo para essa preferência de !boolean?

ell
fonte
28
É mais curto para escrever.
Zenon
39
É como fazer boolean == true: não faz sentido. Expressões dentro de ifinstruções são exatamente isso: expressões. Se algo já é avaliado para uma expressão booleana, por que você adicionaria uma verificação para forçá-lo a avaliar?
Maxpm 25/02/12
10
@zzzzBov: Hum, não. Não é assim que a maioria dos programadores (no estilo C) faz isso.
27612
9
@zzzzBov: Seu comentário é ambíguo. Se você quis dizer que !boolean_variableé assim que a maioria dos programadores C faz, eu concordo.
25412 Keith Thompson
29
E mais importante, como é que ninguém quer escrever boolean != true?

Respostas:

153

Quando vejo uma frase como if (!lateForMeeting()), li isso como "Se não chegar atrasado para a reunião" , o que é bastante simples de entender, em vez de if (lateForMeeting() == false)ler como "Se o fato de estar atrasado para a reunião for falso " .

Eles têm o mesmo significado, mas o primeiro está mais próximo de como a sentença equivalente em inglês seria construída.

kba
fonte
27
+1 Em Python, você realmente escreve if not late_for_meeting:) #
phunehehe
42
Eu afirmo que, se "se ___ for falso" parecer mais natural do que "se não for ___", o nome de ___ precisará ser aprimorado.
Mike DeSimone
12
Em Perl, você pode escreverunless late_for_meeting
Henrik Ripa
4
@HenrikRipa: Parece que qualquer coisa que você pode digitar é um código legal em Perl. Se é ou não faz o que você quer é uma outra questão;)
Adam Robinson
4
@ A-Cube Eu não teria um método assim para começar. Em vez disso, eu teria um método chamado done(). Negativos duplos são ruins.
kba
97

Escrever == falsee == trueé redundante. Também pode ser levado a extremos arbitrários. Se você começar a escrever

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

Então porque não

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

Ou porque não

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

A moral dessa história é que, se conditionfor uma expressão booleana, você não precisará adicionar == false; !é para isso que serve o operador ;)

Andres F.
fonte
Não pensei nisso!
ell
51
== falseNÃO é redundante, apenas mais detalhado que !. OTOH, == trueé redundante.
dan04
4
@ dan04 Você está certo. No entanto, no sentido em que eu quis dizer isso, continua sendo uma má idéia. Considere (exp1 != exp2)vs ((exp1 == exp2) == false). É certo que esses são cenários planejados, mas você quase nunca deve escrever comparações explícitas como verdadeiras ou falsas. Assim como você deve usar o operador !=, também deve usar !.
Andres F.
26
@ dan04: É redundante quando o idioma já oferece !.
DeadMG
5
@ dan04: Toda vez que você escreve bool_expression == bool_literal, == ...é redundante. Se você está testando se é verdadeiro ou falso, é irrelevante. É apenas uma mudança na ordem dos blocos consequentes / alternativos. Os exemplos de Andrés ilustram esse ponto perfeitamente. A maioria dos compiladores modernos otimiza a redundância, mas ainda é redundante.
Lèse majesté
70

Em C e em algumas linguagens similares, comparar expressões booleanas para igualdade falseou trueé um hábito perigoso.

Em C, qualquer expressão escalar (numérica ou ponteiro) pode ser usada em um contexto booleano, por exemplo, como condição de uma ifinstrução. A regra C if (cond)é equivalente a if (cond != 0)- ou seja, zero é falso e qualquer valor diferente de zero é verdadeiro. Se condé do tipo ponteiro, 0é tratado como uma constante de ponteiro nulo; if (ptr)meios if (ptr != NULL).

Isso significa que

if (cond)

e

if (cond == true)

não significa a mesma coisa . O primeiro é verdadeiro se condfor diferente de zero; o segundo é verdadeiro apenas se for igual a true, que em C (se você tiver #include <stdbool.h>) é simplesmente 1.

Por exemplo, a isdigit()função declarada em <ctype.h>retorna um intvalor, 0se o argumento for um dígito, diferente de zero se não for. Pode retornar 42para indicar que a condição é verdadeira. A comparação 42 == truefalhará.

Acontece que esse 0é o único valor considerado falso, portanto, a comparação da igualdade falsefuncionará; if (!cond)e if (cond == false)faça a mesma coisa. Mas se você quiser tirar proveito disso, lembre-se de que comparar com falseestá ok e comparar com truenão. Pior ainda, a comparação com trueo trabalho na maioria das vezes (por exemplo, os operadores de igualdade e relacionais sempre produzem um 0ou outro 1). Isso significa que qualquer bug que você introduz usando isso ainda pode ser difícil de localizar. (Não se preocupe, eles aparecerão assim que você demonstrar o código para um cliente importante.)

C ++ possui regras ligeiramente diferentes; por exemplo, seu booltipo é um pouco mais integrado ao idioma e if (cond)converte condem texto bool. Mas o efeito é (principalmente) o mesmo.

Algumas outras linguagens têm o que se poderia chamar de booleanos mais bem comportados, de modo que cond == truee cond == false(ou seja qual for a sintaxe) seja seguro. Mesmo assim, todas as línguas que eu vi tem um notou !operador; está lá, então você pode usá-lo. Usar, em cond == falsevez de !condou not condnão, na minha opinião, melhora a legibilidade. (É verdade que o !personagem pode ser difícil de ver de relance; às vezes adiciono um espaço após o !para evitar isso.)

E muitas vezes você pode evitar o problema e melhorar a clareza reorganizando o código levemente. Por exemplo, em vez de:

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

você pode escrever:

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

Isso nem sempre é melhor, mas não custa procurar oportunidades onde está.

Resumo: Em C e C ++, as comparações de igualdade truee falsesão perigosas, excessivamente verbais e de estilo pobre. Em muitos outros idiomas, essas comparações podem não ser perigosas, mas ainda são excessivamente verbosas e de estilo pobre.

Keith Thompson
fonte
+1 por esta ser a única resposta com a explicação técnica útil real.
26612 Mike Nakis
Ainda penso assim, independentemente da linguagem de programação, sempre assumo que == truenão é seguro. Parece melhor assim.
Dervall
1
@ Dervall: supondo que algo que simplesmente não é o caso também não é bom. Existem alguns casos de canto em certos idiomas em que a comparação de igualdade de booleanos não é apenas segura, mas de fato apropriada, por exemplo, em Haskell, que possui um forte sistema de tipos sem implícitos com inferência de tipo bidirecional, alguém poderia escrever (==True) . fpara esclarecer que queremos a -> Boolinstanciação da função polimórfica de retorno f. Isso é mais claro not . not . fe menos estranho que (f :: a -> Bool).
leftaroundabout
Além disso, é certamente apropriado fazer coisas como pred(x)==pred(y)para uma função de retorno de bool pred. A alternativa seria a pred(x)? pred(y) : !pred(y)que você concorda que é dificilmente aceitável.
leftaroundabout
1
@leftaroundabout: Tudo bem se você souber disso pred(x)e pred(y)usar o mesmo valor para denotar a verdade, o que é uma suposição segura em alguns idiomas, mas não em outros. Em C, por exemplo, você pode escrever !!pred(x) == !!pred(y).
Keith Thompson
14

Os dois são funcionalmente idênticos, então qual deles usar é uma questão de gosto.

A principal razão que eu uso == falseé que eu acho que !é fácil demais ignorar, ao olhar para o código.

Tendo sido severamente mordido por isso, criei o hábito de deixar bem claro ao testar se é falso.


Se o operador tivesse sido nomeado notcomo em Pascal, não acho que isso se tornaria um problema.

user1249
fonte
5
Por esse motivo, um projeto de C ++ em que trabalhei para algum software de dispositivo médico tinha um padrão de codificação que exigia, em == falsevez de, !pelo mesmo motivo (para destacá-lo). No entanto, não havia necessidade de usar == true, portanto, qualquer valor diferente de zero ainda funcionava como deveria.
tcrosley
12
Eu sempre achei esse argumento pouco convincente - há outros lugares em C / C ++ / C # / Java / etc em que a falha em ver um único caractere tem um impacto igualmente significativo na interpretação do código; destacando "!" como o único mal não faz sentido para mim.
Bevan
5
@bevan Aparentemente você ainda não foi mordido.
1
Embora eu concorde que a negligência !seja provavelmente o erro mais problemático desse tipo, a IMO não deve criar o hábito de escrever, ==falsemas escrever melhores testes de unidade.
leftaroundabout
8
@ ThorbjørnRavnAndersen Muito pelo contrário - fui mordido com bastante frequência ao longo dos anos que me ensinei a ler todos os personagens . Eu não sou o autor de todo (ou mesmo da maioria) do código que tenho que ler dia a dia; portanto, qualquer convenção pessoal que discutimos aqui tem um valor mínimo: preciso entender corretamente todo o código que li, não apenas as coisas que eu escrevi.
Bevan
13

Se condition == falseé realmente "muito mais natural em inglês" para você, devo assumir que você não é um falante nativo. Caso contrário, não posso explicar isso, porque ninguém fala assim:

Se o sol está brilhando, eu fico em casa.

Compare isso com

Se o sol não está brilhando, fico em casa.

Dito isto, concordo que o !caractere único e delgado é facilmente esquecido no código. Por esse motivo, prefiro a palavra-chave notquando suportada pelo idioma. O C ++, por exemplo , permite isso, embora muitos programadores não estejam cientes disso.

Para idiomas que exigem !, coloquei um espaço entre operador e operando. Isso torna muito mais difícil ignorar a negação:

if (! condition) { … }

Observe que todo programador deve traduzir isso automaticamente , sem pensar duas vezes, em "não condicionar" em sua cabeça. Adquirir esse tipo de fluência na leitura de idiomas de código está entre os primeiros passos para se tornar um bom programador.

Konrad Rudolph
fonte
6

porque às vezes você pode escrever boolean = false(com os erros óbvios) e false == booleannão parece natural (não importa quão boa seja a prática)

catraca arrepiante
fonte
Há muito tempo, quando comecei a programar, um mentor meu sugeriu que eu tivesse o hábito de fazer if( INVALID_HANDLE_VALUE == hFile )para evitar coisas assim. Dessa forma, se você escorregar e usar um sinal de igual em vez de dois, receberá um erro do compilador. Obviamente, isso só funciona quando a expressão esquerda é uma constante, mas me salvou mais dores de cabeça do que posso contar.
Desenhou Chapin
se você usar uma ferramenta de análise estática, você economizará cem vezes mais dores de cabeça e poderá restaurar a natureza hFile==INVALID_HANDLE_VALUE .
Gqqnbig
4

if (!boolean_variable)traduz para if the condition is not true.

if (boolean == false)traduz para if the condition not false is true. Porque essa é a lógica inversa, é mais difícil de entender.

BЈовић
fonte
3
! true significa não é verdade. ! booleano significa não falso ou não é verdadeiro, dependendo do valor do booleano, que por si só é uma inversão lógica.
26412 S.Robins
1
@ S.Robins Acho o nome estúpido de booleano para uma variável booleana. Algo como, por exemplo, isVisibleseria um exemplo melhor. Então if (!isVisible)significaria se não estiver visível - o que é mais simples de entender if (isVisible==false), que é uma lógica inversa. Espero que esteja mais claro agora. Ou entendi mal o seu comentário?
BЈовић
2

Em compiladores (muito) mais antigos, acredito que eles quebrariam (booleano == false) em duas atribuições de registro e um código de comparação em linguagem de máquina. O primeiro exemplo seria dividido em uma atribuição e um operador NOT. Em termos de desempenho, a operação de comparação levaria vários ciclos de clock, dependendo do tamanho do registro sendo comparado, comparado a um invertido bit a bit (1 clock) e seria mais lenta de executar.

Dito isto, acredito que os compiladores mais recentes acabam com isso, então deve ser bom seguir com eles.

lcllam
fonte
Gerando código de máquina é o trabalho do compilador, não o alto nível de língua programador de ...
um CVn
Por razões históricas, essa pode muito bem ser uma das razões pelas quais um método se tornou preferido em relação ao outro.
Legolas
1

No trabalho, muitas vezes estou lidando com booleanos, que podem ser nulos; portanto, codificarei esse caso como

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

porque eu pessoalmente sinto que a simetria facilita a leitura. Especialmente se houver outros booleanos sendo testados também.

Eu realmente não me importo de um jeito ou de outro.

WuHoUnited
fonte
4
se value == truenão houver motivo para verificar se não é nulo. Se a value == nullinstrução nunca deve acionar a instrução if em primeiro lugar, isso if (value)deve ser suficiente.
zzzzBov
1
Booleanos são objetos (em java) e, portanto, podem ser nulos; portanto, basta dizer que if (value)lança uma exceção. Eu apreciaria se as pessoas que votaram negativamente deram uma razão.
WuHoUnited
3
Acabei de ver isso, não diminuiu. Nulo booleano não é uma boa prática. Por quê? porque booleano geralmente representa um estado de algo ativado ou desativado. Na maioria dos casos, você deve declarar falso no início e depois alterá-lo junto com o comportamento. É muito incomum ver booleano não sendo inicializado.
Beringela
Eu tenho que concordar com a Beringela aqui, eu mesmo caí no mau hábito (especialmente em Java) de deixar os bools não inicializados e, em seguida, acabo verificando se há nulo. Eu acho que isso é mais uma falha da linguagem, no entanto, que impõe essa falha ao usuário. Ao declarar uma nova variável bool, ela deve ser padronizada como false sem inicialização na minha opinião.
2
@WuHoUnited, mesmo se o valor for nulo, value == trueseria suficiente.
precisa saber é o seguinte
1

Quando você está testando a condição verdadeira, faz sentido fazer exatamente isso if (condition), especialmente quando você aplica a convenção de nomear variáveis ​​booleanas começando com 'is': if (isOpen)é perfeitamente claro e o uso != falseseria redundante.

Para um C / C ++ / Java / etc. programador, o significado do '!' O operador é completamente assimilado, a tal ponto que automaticamente "não" temos em nossas mentes quando o vemos. Então, ter if (!isOpen)é tão claro quanto if (_NOT_ isOpen)para mim. Mas você não está familiarizado o suficiente, com o C / C ++ você pode criar uma macro #define _NOT_ !. Mas confie em mim, depois de alguns anos isso é completamente desnecessário.

Além disso, é sempre preferível testar valores booleanos sem compará-los com literais. Por exemplo, é perigoso testar if (x == true)porque um valor booleano é considerado verdadeiro se não for zero, e o literal verdadeiro possui apenas um valor específico; portanto, x pode ser 'verdadeiro' (ou seja, diferente de zero) e ainda assim a comparação é avaliada como falsa (porque contém 2 e o literal verdadeiro é, digamos, 1.) É claro que isso não se aplica a uma comparação com false, mas se você não o usa ao testar para true, por que usá-lo ao testar para false?

Fabio Ceconello
fonte
Não é necessário criar a macro C ++ que você propõe, pois o C ++ já entende 'não'. Relacionados: stackoverflow.com/questions/2393673/c-and-or-not-xor-keywords
frozenkoi
Isso é verdade, mas é uma palavra-chave apenas para o padrão C ++ 0X. Antes disso, era apenas mais uma macro.
Fabio Ceconello
0

Tamanho importa ;)

Em expressões mistas, é mais fácil ler:

boolean1 = false
boolean2 = true

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

E especial para o ruby, um exemplo em que há uma grande diferença:

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

nulo não é falso, mas também não é verdadeiro.

knut
fonte
0

Baseado na minha experiência e nas respostas da minha pergunta à qual você se vinculou.

Algumas pessoas preferem usar if (condição), pelo motivo que é mais curto para escrever. e para mim, na verdade, faz sentido, por exemplo (! isValidated ()) eu li isso como Não validado. mas, para mim, tudo é baseado em preferências pessoais e depende da estrutura lógica do método isValidated (), se retornar verdadeiro ou falso

KyelJmD
fonte
0

Se você nomeou sua variável corretamente, !booleané mais natural. Ele lê como not booleanpara quem é programador suficiente para ler código mentalmente.

Corridas de leveza com Monica
fonte
0

Para algumas pessoas, quanto mais cedo um significado for expresso, melhor.

Para as pessoas que têm "se! ..." se compara mais rapidamente com "se ...", então precisam ler toda a condição (que pode ser bem longa, por exemplo (thisThing = thatThing ou algo = a outra coisa) OR ( thinga = thingb e thinga = thingd), etc.) apenas para encontrar o == false no final.

Tendo o! (Na verdade, prefiro não quando o idioma o permite) logo de cara o inglês não é 'não' para essa condição.

Esse problema também leva em consideração o uso untilem idiomas que o suportam, por exemplo, faça 'coisas comuns' até que tudo termine. Como outros dizem, a expressão da linguagem natural é o objetivo. Eu gosto do exemplo "o sol está brilhando" acima.

viciado
fonte
0

Outro motivo é que, se você estiver trabalhando em uma base de código que usa vários idiomas, se houver uma maneira idiomática de fazer algo seguro em todos os idiomas, é uma boa idéia fazê-lo dessa maneira em qualquer lugar, para que você forme um bom hábito e são menos propensos a tropeçar.

Não consigo pensar em nenhum lugar que if (!variable)(ou equivalente, if not variabledependendo da sua linguagem) não seja seguro, enquanto, por exemplo, if self.is_ready() == False: ...não é seguro em python se self.is_ready()retornar None, agora ou no futuro, o que seria uma coisa totalmente razoável de fazer. indicar que não estava pronto, pois Noneé tão falsa quanto False.

daphtdazz
fonte