Por que o PHP trata "0" como FALSE em contextos booleanos?

12

"0", como uma string contendo um caractere, não é algo vazio intuitivamente. Por que o PHP o trata como FALSE quando convertido em um booleano, diferente de outras linguagens de programação?

Michael Tsang
fonte
2
duplicado de: stackoverflow.com/questions/523643/… . É o mesmo no PHP e no javascript. Verifique a resposta abaixo da resposta aceita.
21416 Walfrat
5
É porque o PHP faz o possível para ser o mais inconsistente, tanto com ele próprio quanto com qualquer outra linguagem de programação possível.
David Arno
2
@DavidArno Pelo contrário, está fazendo o possível para ser consistente ; Depois de iniciar as seqüências de autasting (muito útil em um idioma que geralmente pega vars de URLs ou corpos de solicitação), você precisa seguir essa lógica. Se '0'é tratado como 0em $x + 1, por que não deveria também ser tratado como 0e false, portanto , em if ( $x )?
IMSoP
1
@DavidArno exatamente;)
linuxunil
1
@DavidArno Depois que você começa a realizar lançamentos com perdas, acho que é inevitável alguma inconsistência; a solução consistente envolve rejeitar alguns modelos e projetar o restante com muito cuidado. Muito poucos idiomas populares são projetados a partir do zero; a maioria evolui de experimentos populares acidentalmente ou de idiomas mais antigos com diferentes objetivos e bagagem. Até o C #, que tem muito design teórico sólido, tem algum legado do C, que nunca teve a intenção de ser tão universal quanto se tornou. Snark como "esforçar-se para ser inconsistente" é como gritar com o árbitro em uma partida esportiva.
IMSOP

Respostas:

12

O PHP foi projetado (ou melhor, evoluído) para uso com solicitações da Web, nas quais você frequentemente lida com a entrada de string (parâmetros de URL ou solicitações POST de um formulário em um navegador). Como tal, ele converterá automaticamente seqüências para outros tipos.

Um exemplo simples disso é que '1' + '2'fornece 3, não um erro, ou '12'ou alguma outra interpretação. Pela mesma lógica, a cadeia '0'pode ser usada como numérica 0.

Enquanto isso, como muitas linguagens, o PHP trata certos valores como "falsy" quando convertidos em booleanos - aqueles que são intuitivamente "vazios", como você diz. Isso inclui numérico 0, bem como a sequência vazia ''e a matriz vazia []. Em uma ifdeclaração, a expressão é explicitamente convertida em booleana, e if ( 0 )é a mesma que if ( false ).

Ao juntar essas duas coisas, você obtém um enigma: por um lado, como você diz, '0'é uma string não vazia; por outro lado, dissemos que ele pode ser usado como numérico 0, que é "vazio". O PHP opta por tratar o "zero-ness" como mais importante que o "rigor", de modo que '0'é considerado "falso".

Em suma '0' == 0 == false:; ou(bool)'0' === (bool)(int)'0'

IMSoP
fonte
Alguém negou minha resposta apenas porque me atrevi a defender o PHP e a responder à pergunta com algo que não fosse uma piada barata e ignorante? Ou há algo impreciso ou inútil na minha resposta que eles gostariam de salientar?
IMSOP
1
Eu acho que o PHP tirou isso do Perl, que tem o mesmo "0" comportamento " é falso". Em Perl, há, literalmente, não há qualquer diferença visível ao usuário entre a corda "0"e número 0- irritante ao manusear JSON, mas muito intuitiva ao manusear dados textuais. É então impossível ter o número0 seja falsey sem que a string também "0"seja falsey. PHP e JavaScript emprestado esta decisão design, mas adicionar um pouco de confusão, distinguindo cordas / bools / tipos numéricos, enquanto ainda permitindo conversões implícitas (PHP: 0 == "0 foo", 0 == false, mas "0 foo" == true: ==não é transitiva)
amon
@amon Sim, o Perl adota a abordagem interessante de (quase) todos os operadores e funções internas que forçam operandos a um tipo específico, com operadores extras, como eqa igualdade de cadeias. No entanto, isso não o salva da não transitividade de elencos com perdas: "0 foo"é verdade em um contexto booleano, mas é igual a 0under ==. Então, if ( ! $foo ) ..e $false = (1 == 2); if ( $foo == $false ) ... não dê o mesmo resultado. Eu acho que o idioma está faltando um operador "boolean igualdade", que poderia tratar isso de forma consistente ...
IMSOP
Embora "0" seja 0 quando avaliado como numérico, quando usamos uma string em um contexto booleano (por exemplo, em uma instrução if), não estamos interessados ​​em seu valor numérico. Se quisermos interpretá-lo como numérico, o compararemos com algum número, por exemplo $_POST['id'] == 0, que deixa claro a intenção de que queremos tratar a entrada do usuário como um número.
Michael Tsang
1
@MestreLion Esse exemplo foi do Perl, e não do PHP. A diferença crucial é que não há um tipo booleano separado no Perl, então$false definido como 0; portanto, quando você escreve $foo == $false, o Perl não sabe que deseja uma comparação booleana e, em vez disso, lança o int. No PHP, isso não acontece, porque $falseé booleano false e, portanto, é ==convertido em booleano, resultando no mesmo resultado que!
#
3

De acordo com a documentação do PHP sobre booleanos , ele diz que:

Ao converter para booleano, os seguintes valores são considerados FALSE
...
a sequência vazia e a sequência "0"
...

De outra forma:

Qualquer outro valor é considerado VERDADEIRO (incluindo qualquer recurso).

Se você executar:

var_dump((bool) "0");

Irá imprimir:

bool (false)

Então, está funcionando como esperado.


Para responder explicitamente à sua pergunta:

No entanto, na maioria dos casos, a conversão é desnecessária, pois um valor será convertido automaticamente se um operador, função ou estrutura de controle exigir um argumento booleano.

Isso significa que o "autocast" do PHP converterá "0" no número inteiro 0, que também está FALSEem uma estrutura de controle como digamos umif() declaração.

kayess
fonte
Gostaria de conhecer a lógica da decisão de design tratando "0" como FALSE quando convertido em booleano, em vez da necessidade de conversão explícita.
Michael Tsang