Как оператор космического корабля PHP <=> обрабатывает несопоставимые операнды?

В PHP 7 будет добавлен оператор космического корабля. Я не уверен, как он работает в некоторых крайних случаях.

$a <=> $b вернусь:

  • 1 если $a> $ b
  • 0 если $a == $ b
  • -1 если $a <$ b

Что произойдет, если значения не сопоставимы?

Какие типы переменных можно сравнить?

1 ответ

Решение

Просто! Запрос на тягу, в котором реализован оператор, относится к функции с именем compare_function во внутренностях PHP, так что вам просто нужно прочитать compare_function 200-строчная реализация макро-тяжелого C, и вы сможете понять поведение для себя. Структуры управления имеют глубину всего 4 уровня, и вызывается всего несколько десятков макросов и других функций; это должно быть легко!

...

Хорошо, я признаю это, я не достаточно умен, чтобы снять все это. Так что давайте просто сделаем несколько экспериментов.

Если <, == а также > может обрабатывать операнды последовательно, то так может <=>

Большинство типов в PHP можно сравнивать с другими типами благодаря жонглированию типов. В любом случае, оператор космического корабля будет вести себя так, чтобы <, == а также >,

Например, давайте попробуем использовать строку и int:

php > var_dump(3 < 'bla');
bool(false)
php > var_dump(3 == 'bla');
bool(false)
php > var_dump(3 > 'bla');
bool(true)
php > var_dump(3 <=> 'bla');
int(1)

Или с null и ресурс:

php > $fp = fopen('test', 'r');
php > var_dump(null > $fp);
bool(false)
php > var_dump(null == $fp);
bool(false)
php > var_dump(null < $fp);
bool(true)
php > var_dump(null <=> $fp);
int(-1)

Или с плавающей точкой и массивом:

php > var_dump(1.0 > []);
bool(false)
php > var_dump(1.0 == []);
bool(false)
php > var_dump(1.0 < []);
bool(true)
php > var_dump(1.0 <=> []);
int(-1)

Во всех этих случаях результат $a <=> $b именно так и должно быть в документах: -1 если $a < $b, 0 если $a == $b, а также 1 если $a > $b,

Но если ни один из <, == а также > вернуть истину, космический корабль запутывается и возвращает 1

Хотя приведение типов позволяет сравнивать большинство значений различных типов друг с другом, так что ровно одно из $a < $b, $a == $b а также $a > $b Это правда, есть несколько крайних случаев, в которых это не имеет места. В этих случаях результат $a <=> $b 1, что не очень значимо или полезно.

Например, давайте сравним несколько объектов разных классов:

php > class Foo {}
php > class Bar {}
php > $a = new Foo;
php > $b = new Bar;
php > var_dump($a < $b);
bool(false)
php > var_dump($a == $b);
bool(false)
php > var_dump($a > $b);
bool(false)
php > var_dump($a <=> $b);
int(1)
php > var_dump($b <=> $a);
int(1)

или некоторые неравные массивы, где ни один строго не больше другого:

php > $a = ['foo' => 'bar'];
php > $b = ['bar' => 'foo'];
php > var_dump($a < $b);
bool(false)
php > var_dump($a == $b);
bool(false)
php > var_dump($a > $b);
bool(false)
php > var_dump($a <=> $b);
int(1)
php > var_dump($b <=> $a);
int(1)

<=> также может бросать предупреждения

Если мы сравниваем объект с int, мы получаем предупреждение, как если бы мы делали это с любым другим оператором сравнения:

php > $a = new stdclass;
php > var_dump($a <=> 1);
PHP Notice:  Object of class stdClass could not be converted to int in php shell code on line 1
int(0)

Результаты для несопоставимых типов, очевидно, бесполезны и могут запутать все, что ожидает от оператора космического корабля последовательного упорядочения значений различных типов. Так что не используйте его в обстоятельствах, когда он может делать бессмысленные сравнения, подобные этим.

Другие вопросы по тегам