Mengapa PHP memperlakukan "0" sebagai FALSE dalam konteks boolean?

12

"0", sebagai string yang berisi satu karakter, bukanlah sesuatu yang kosong secara intuitif. Mengapa PHP memperlakukannya sebagai SALAH ketika dikonversi ke boolean, tidak seperti bahasa pemrograman lainnya?

Michael Tsang
sumber
2
duplikat: stackoverflow.com/questions/523643/… . Sama di PHP dan javascript, periksa jawaban di bawah ini.
Walfrat
5
Itu karena PHP berusaha keras untuk menjadi tidak konsisten, dengan dirinya sendiri dan setiap bahasa pemrograman lainnya, sebanyak mungkin.
David Arno
2
@ Davidvido Sebaliknya, itu melakukan yang terbaik untuk konsisten ; setelah Anda memulai string autocasting (sangat berguna dalam bahasa yang sering mengambil vars dari URL atau badan permintaan) Anda harus mengikuti logika itu. Jika '0'diperlakukan seperti 0dalam $x + 1, mengapa itu tidak juga diperlakukan sebagai 0, dan karenanya false, masuk if ( $x )?
IMSoP
1
@ Davidvidno persis;)
linuxunil
1
@ Davidvido Setelah Anda mulai melakukan cast lossy, beberapa inkonsistensi tidak bisa dihindari saya pikir; solusi konsisten melibatkan menolak beberapa gips, dan merancang sisanya dengan sangat hati-hati. Sangat sedikit bahasa populer yang dirancang dari awal; sebagian besar berevolusi baik dari eksperimen populer yang tidak sengaja, atau dari bahasa yang lebih tua dengan tujuan dan bagasi yang berbeda. Bahkan C #, yang memiliki banyak desain teoritis suara, memiliki beberapa warisan dari C, yang tidak pernah dimaksudkan untuk menjadi seuniversal dulu. Snark seperti "berusaha keras untuk menjadi tidak konsisten" seperti berteriak pada wasit di pertandingan olahraga.
IMSoP

Jawaban:

12

PHP dirancang (atau, lebih tepatnya, dikembangkan) untuk digunakan dengan permintaan web, tempat Anda sering berurusan dengan input string (parameter URL, atau permintaan POST dari formulir di browser). Dengan demikian, secara otomatis akan melemparkan string ke tipe lain.

Contoh sederhana dari ini adalah yang '1' + '2'memberi 3, bukan kesalahan, atau '12', atau beberapa interpretasi lainnya. Dengan logika yang sama, string '0'dapat digunakan sebagai numerik 0.

Sementara itu, seperti banyak bahasa, PHP memperlakukan nilai-nilai tertentu sebagai "falsy" ketika dilemparkan ke boolean - yang secara intuitif "kosong", seperti yang Anda katakan. Itu termasuk numerik 0, serta string kosong ''dan array kosong []. Dalam sebuah ifpernyataan, ekspresi secara eksplisit dilemparkan ke boolean, jadi if ( 0 )sama dengan if ( false ).

Menyatukan kedua hal ini, Anda mendapatkan teka-teki: di satu sisi, seperti yang Anda katakan '0'adalah string yang tidak kosong; di sisi lain, kita telah mengatakan bahwa itu dapat digunakan sebagai numerik 0, yaitu "kosong". PHP memilih untuk memperlakukan "zero-ness" sebagai lebih penting daripada "stringiness", sehingga '0'dianggap "falsy".

Singkatnya '0' == 0 == false:; atau(bool)'0' === (bool)(int)'0'

IMSoP
sumber
Apakah ada orang yang menurunkan jawaban saya hanya karena saya berani membela PHP dan menjawab pertanyaan dengan sesuatu selain lelucon yang murah dan tidak acuh? Atau ada sesuatu yang tidak akurat atau tidak membantu dalam jawaban saya yang ingin mereka tunjukkan?
IMSoP
1
Saya pikir PHP mengambil ini dari Perl, yang memiliki "0" perilaku "salah" yang sama. Di Perl, secara harfiah tidak ada perbedaan yang terlihat oleh pengguna antara string "0"dan angka 0- menjengkelkan saat menangani JSON, tetapi sangat intuitif saat menangani data tekstual. Maka tidak mungkin untuk memiliki nomor 0menjadi falsey tanpa juga string "0"menjadi falsey. PHP dan JavaScript meminjam keputusan desain ini, tetapi menambahkan beberapa kebingungan dengan membedakan string / bools / jenis numerik sementara masih memungkinkan konversi implisit (PHP: 0 == "0 foo", 0 == false, tetapi "0 foo" == true: ==tidak transitif)
Amon
@amon Ya, Perl mengambil pendekatan yang menarik dari (hampir) semua operator dan fungsi bawaan yang memaksa operan ke jenis tertentu, dengan operator tambahan seperti equntuk kesetaraan string. Namun, ini tidak menyelamatkannya dari non-transitivitas pemain "0 foo"yang hilang : benar dalam konteks boolean, tetapi sama dengan di 0bawah ==. Jadi if ( ! $foo ) ..dan $false = (1 == 2); if ( $foo == $false ) ... jangan memberikan hasil yang sama. Saya kira bahasanya tidak ada operator "kesetaraan boolean" yang dapat memperlakukan ini secara konsisten ...
IMSoP
Meskipun "0" adalah 0 ketika dievaluasi sebagai numerik, ketika kami menggunakan string dalam konteks boolean (misalnya dalam pernyataan if), kami tidak tertarik dengan nilai numeriknya. Jika kita ingin menafsirkannya sebagai angka, kita akan membandingkannya dengan beberapa angka, misalnya $_POST['id'] == 0, yang membuat maksudnya jelas bahwa kita ingin memperlakukan input pengguna sebagai angka.
Michael Tsang
1
@MestreLion Contoh itu dari Perl daripada PHP. Perbedaan penting adalah bahwa tidak ada tipe boolean yang terpisah di Perl, jadi $falseakhirnya diatur ke 0; jadi ketika Anda menulis $foo == $false, Perl tidak tahu Anda ingin perbandingan boolean, dan gips ke int. Di PHP, itu tidak terjadi, karena $falseboolean false, jadi ==dilemparkan ke boolean, memberikan hasil yang sama seperti!
IMSoP
3

Menurut dokumentasi PHP tentang booleans , dikatakan bahwa:

Saat mengonversi ke boolean, nilai berikut dianggap FALSE
...
string kosong, dan string "0"
...

Jika tidak:

Setiap nilai lainnya dianggap BENAR (termasuk sumber daya apa pun).

Jika Anda menjalankan:

var_dump((bool) "0");

Itu akan mencetak:

bool (salah)

Jadi itu berfungsi seperti yang diharapkan.


Untuk secara eksplisit menjawab pertanyaan Anda:

Namun, dalam banyak kasus para pemain tidak perlu, karena nilai akan secara otomatis dikonversi jika operator, fungsi atau struktur kontrol memerlukan argumen boolean.

Ini berarti bahwa PHP "autocast" akan menampilkan "0" ke integer 0, yang FALSEjuga dalam struktur kontrol seperti mengucapkan if()pernyataan.

kayess
sumber
Saya ingin mengetahui alasan keputusan desain yang memperlakukan "0" sebagai FALSE ketika dikonversi ke boolean, daripada kebutuhan casting eksplisit.
Michael Tsang