Почему PHP рассматривает «0» как ЛОЖЬ в логических контекстах?


12

«0», как строка, содержащая один символ, не является чем-то пустым интуитивно. Почему PHP обрабатывает его как FALSE при преобразовании в логическое значение, в отличие от других языков программирования?


2
дубликат: stackoverflow.com/questions/523643/… . Это как в PHP, так и в JavaScript. Проверьте ответ ниже принятого ответа.
Вальфрат

5
Это потому, что PHP делает все возможное, чтобы быть как можно более непоследовательным, как с самим собой, так и с любым другим языком программирования.
Дэвид Арно

2
@DavidArno Напротив, он старается быть последовательным ; как только вы начнете автопередачу строк (очень удобно на языке, часто собирающем переменные с URL-адресов или тел запросов), вы должны следовать этой логике. Если '0'трактуется как 0в $x + 1, почему он не должен рассматриваться как 0, и, следовательно false, в if ( $x )?
IMSoP

1
@DavidArno точно;)
linuxunil

1
@DavidArno Как только вы начнете выполнять броски с потерями, некоторая несогласованность неизбежна; непротиворечивое решение включает отказ от некоторых забросов и тщательное проектирование остальных. Очень немногие популярные языки разработаны с нуля; большинство эволюционируют либо из случайно-популярных экспериментов, либо из более старых языков с разными целями и багажом. Даже C #, который имеет много теоретического дизайна, имеет некоторое наследие от C, который никогда не был настолько универсальным, каким он стал. Снарк, как «идти на все, чтобы быть непоследовательным», это все равно, что кричать на рефери в спортивном матче.
IMSoP

Ответы:


12

PHP был разработан (или, скорее, развит) для использования с веб-запросами, когда вы часто имеете дело со строковым вводом (параметры URL или запросы POST из формы в браузере). Таким образом, он будет автоматически приводить строки к другим типам.

Простым примером этого является то , что '1' + '2'дает 3, а не ошибку, или '12', или некоторую другую интерпретацию. По той же логике, строка '0'может быть использована в качестве числа 0.

Между тем, как и во многих языках, PHP обрабатывает определенные значения как «ложные» при приведении к логическим значениям, которые, как вы говорите, интуитивно «пусты». Это включает в себя числовые 0, а также пустую строку ''и пустой массив []. В ifутверждении выражение явно приведено к логическому значению, так if ( 0 )же как и if ( false ).

Соединяя эти две вещи вместе, вы получаете загадку: с одной стороны, как вы говорите, '0'непустая строка; с другой стороны, мы сказали, что он может быть использован как числовой 0, который является «пустым». PHP предпочитает рассматривать «ноль» как более важный, чем «неровность», так что '0'это считается «ложью».

Короче говоря '0' == 0 == false:; или(bool)'0' === (bool)(int)'0'


Кто-то опроверг мой ответ только потому, что я осмелился защитить PHP и ответить на вопрос чем-то другим, кроме дешевой и неосведомленной шутки? Или в моем ответе есть что-то неточное или бесполезное, на что они хотели бы указать?
IMSoP

1
Я думаю, что PHP взял это от Perl, который ведет себя так же, как « "0" ложь». В Perl буквально нет видимой пользователем разницы между строкой "0"и числом 0- это раздражает при обработке JSON, но очень интуитивно понятно при обработке текстовых данных. В таком случае невозможно, чтобы число 0было ложным, если бы строка не "0"была ложной. PHP и JavaScript позаимствовать это проектное решение, но добавить некоторую путаницу, различая струнные / Bools / числовых типов в то же время позволяя неявные преобразования (PHP: 0 == "0 foo", 0 == false, но "0 foo" == true: ==не транзитивно)
Амон

@amon Да, Perl использует интересный подход (почти) всех операторов и встроенных функций, заставляющих операнды определенного типа, с дополнительными операторами, например, eqдля равенства строк. Тем не менее, это не спасает его от "0 foo"нетранзитивности бросков с потерями: верно в логическом контексте, но равно 0under ==. Так что if ( ! $foo ) ..и $false = (1 == 2); if ( $foo == $false ) ... не дайте того же результата. Я предполагаю, что в языке отсутствует оператор «логического равенства», который мог бы обрабатывать это последовательно ...
IMSoP

Хотя «0» равно 0, когда оценивается как числовое, когда мы используем строку в логическом контексте (например, в операторе if), нас не интересует ее числовое значение. Если мы хотим интерпретировать его как числовое, мы бы сравнили его, например, с некоторым числом $_POST['id'] == 0, что ясно дает понять, что мы хотим обрабатывать ввод пользователя как число.
Майкл Цанг

1
@MestreLion Этот пример был с Perl, а не с PHP. Принципиальное отличие заключается в том, что в Perl нет отдельного логического типа, поэтому в $falseконечном итоге устанавливается значение 0; поэтому, когда вы пишете $foo == $false, Perl не знает, что вы хотите логическое сравнение, и вместо этого приводит к int. В PHP этого не происходит, потому что $falseэто логическое значение false, поэтому используется ==логическое значение, которое дает тот же результат, что и!
IMSoP

3

Согласно документации PHP на логические значения , это говорит о том, что:

При преобразовании в логическое значение учитываются следующие значения FALSE
...
пустая строка и строка "0"
...

В противном случае:

Любое другое значение считается ИСТИННЫМ (включая любой ресурс).

Если вы запускаете:

var_dump((bool) "0");

Он напечатает:

BOOL (ложь)

Так что работает как положено.


Чтобы четко ответить на ваш вопрос:

Однако в большинстве случаев приведение не требуется, поскольку значение будет автоматически преобразовано, если для оператора, функции или структуры управления требуется логический аргумент.

Это означает, что «автоматическая трансляция» в PHP преобразует «0» в целое число 0, что также находится FALSEв управляющей структуре, такой как, например, if()оператор.


Я хотел бы знать обоснование проектного решения, трактующего «0» как ЛОЖЬ при преобразовании в логическое значение, а не необходимость явного приведения.
Майкл Цанг
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.