Perché PHP tratta "0" come FALSO in contesti booleani?


12

"0", come una stringa contenente un carattere, non è qualcosa di vuoto intuitivamente. Perché PHP lo considera FALSO quando convertito in un valore booleano, a differenza di altri linguaggi di programmazione?


2
duplicato di: stackoverflow.com/questions/523643/… . È lo stesso in PHP e javascript, controlla la risposta sotto la risposta accettata.
Walfrat,

5
È perché PHP fa di tutto per essere il più incoerente, sia con se stesso che con ogni altro linguaggio di programmazione possibile.
David Arno,

2
@DavidArno Al contrario, sta facendo del suo meglio per essere coerente ; una volta che avvii le stringhe di autocasting (molto utili in una lingua che spesso acquisisce var da URL o corpi di richiesta) devi seguire quella logica. Se '0'viene trattato come 0in $x + 1, perché non dovrebbe essere trattato anche come 0, e quindi false, in if ( $x )?
IMSoP

1
@DavidArno esattamente;)
linuxunil,

1
@DavidArno Una volta che inizi a eseguire cast con perdita di dati, penso che alcune incongruenze siano inevitabili; la soluzione coerente prevede il rifiuto di alcuni cast e la progettazione del resto con molta attenzione. Tuttavia, pochissime lingue popolari sono progettate da zero; la maggior parte si evolve da esperimenti accidentalmente popolari o da lingue più vecchie con scopi e bagagli diversi. Perfino C #, che ha un sacco di design teorico del suono, ha un po 'di eredità da C, che non è mai stata pensata per essere così universale come è diventata. Snark come "fare di tutto per essere incoerente" è come gridare all'arbitro in una partita sportiva.
IMSoP

Risposte:


12

PHP è stato progettato (o, piuttosto, evoluto) per l'uso con richieste Web, in cui hai spesso a che fare con l'input di stringhe (parametri URL o richieste POST da un modulo in un browser). Come tale, lancerà automaticamente le stringhe su altri tipi.

Un semplice esempio di ciò è che '1' + '2'fornisce 3, non un errore, o '12', o qualche altra interpretazione. Secondo la stessa logica, la stringa '0'può essere utilizzata come un numero 0.

Nel frattempo, come molte altre lingue, PHP tratta alcuni valori come "falsi" quando espressi in booleani - quelli che sono intuitivamente "vuoti", come dici tu. Ciò include i valori numerici 0, nonché la stringa vuota ''e l'array vuoto []. In una ifdichiarazione, l'espressione è esplicitamente lanciata su booleana, quindi if ( 0 )è la stessa di if ( false ).

Mettendo insieme queste due cose, ottieni un enigma: da un lato, come dici tu '0'è una stringa non vuota; d'altra parte, abbiamo detto che può essere usato come un numero 0, che è "vuoto". PHP sceglie di considerare la "nullità" più importante della "rigidità", quindi '0'viene considerata "falsa".

In breve '0' == 0 == false:; o(bool)'0' === (bool)(int)'0'


Qualcuno ha declassato la mia risposta solo perché ho osato difendere PHP e rispondere alla domanda con qualcosa di diverso da uno scherzo economico e ignorante? O c'è qualcosa di inaccurato o di inutile nella mia risposta che vorrebbero sottolineare?
IMSoP

1
Penso che PHP abbia preso questo da Perl, che ha lo stesso "0" comportamento "falso". In Perl, non c'è letteralmente alcuna differenza visibile dall'utente tra la stringa "0"e il numero 0- fastidioso quando si gestisce JSON, ma molto intuitivo quando si gestiscono dati testuali. È quindi impossibile che il numero 0sia falso senza che anche la stringa "0"sia falsa. PHP e JavaScript prendere in prestito questa decisione di progettazione, ma aggiungere un po 'di confusione distinguendo stringhe / Caccio / tipi numerici, pur consentendo conversioni implicite (PHP: 0 == "0 foo", 0 == false, ma "0 foo" == true: ==non è transitiva)
amon

@amon Sì, Perl adotta l'approccio interessante di (quasi) tutti gli operatori e le funzioni integrate forzando gli operandi a un tipo particolare, con operatori extra come eqper l'uguaglianza delle stringhe. Tuttavia, questo non lo salva dalla non transitività dei calchi in perdita: "0 foo"è vero in un contesto booleano, ma è uguale a 0under ==. Quindi if ( ! $foo ) ..e $false = (1 == 2); if ( $foo == $false ) ... non dare lo stesso risultato. Immagino che alla lingua manchi un operatore di "uguaglianza booleana" che potrebbe trattarlo in modo coerente ...
IMSoP

Sebbene "0" sia 0 quando valutato come numerico, quando utilizziamo una stringa in un contesto booleano (ad esempio in un'istruzione if), non siamo interessati al suo valore numerico. Se vogliamo interpretarlo come un valore numerico, lo confronteremmo con un numero, ad esempio $_POST['id'] == 0, il che chiarisce l'intenzione che vogliamo trattare l'input dell'utente come un numero.
Michael Tsang,

1
@MestreLion Quell'esempio era di Perl piuttosto che di PHP. La differenza cruciale è che non esiste un tipo booleano separato in Perl, quindi $falsefinisce con 0; quindi quando scrivi $foo == $false, Perl non sa che vuoi un confronto booleano e lancia invece int. In PHP, ciò non accade, perché $falseè booleano falso, quindi viene ==lanciato in booleano, dando lo stesso risultato di!
IMSoP

3

Secondo la documentazione di PHP sui booleani , si dice che:

Quando si converte in booleano, vengono considerati i seguenti valori FALSE
...
la stringa vuota e la stringa "0"
...

Altrimenti:

Ogni altro valore è considerato VERO (compresa qualsiasi risorsa).

Se corri:

var_dump((bool) "0");

Stampa:

bool (false)

Quindi funziona come previsto.


Per rispondere esplicitamente alla tua domanda:

Tuttavia, nella maggior parte dei casi il cast non è necessario, poiché un valore verrà automaticamente convertito se un operatore, una funzione o una struttura di controllo richiedono un argomento booleano.

Ciò significa che "autocast" di PHP eseguirà il cast di "0" FALSEnell'intero 0, che si trova anche in una struttura di controllo come dire if()un'istruzione.


Mi piacerebbe conoscere la logica della decisione di progettazione che tratta "0" come FALSO quando convertito in booleano, piuttosto che la necessità di un cast esplicito.
Michael Tsang,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.