【问题标题】:How does PHP's spaceship operator <=> handle incomparable operands?PHP 的宇宙飞船运算符 <=> 如何处理不可比的操作数?
【发布时间】:2015-09-03 19:50:04
【问题描述】:

将在 PHP 7 中添加 spaceship 运算符。我不确定它在某些边缘情况下如何工作。

$a &lt;=&gt; $b 将返回:

  • 1 如果 $a > $b
  • 0 如果 $a == $b
  • -1 如果 $a

如果这些值不可比较会怎样?

可以比较哪些变量类型?

【问题讨论】:

  • RFC 说 “它是通过使用现有的内部 compare_function 的结果来实现的,该函数是其他比较运算符的基础。” 从表格来看,它似乎会执行方式与其他比较运算符相同。

标签: php-7 spaceship-operator


【解决方案1】:

简单!在 PHP 内部实现操作符 defers to a function called compare_function 的拉取请求,因此您只需阅读宏重 C 的 compare_function 的 200-line implementation 即可了解其行为。控制结构只有 4 层深,只有几十个宏和其他函数被调用;应该很容易!

...

好吧,我承认,我也不够聪明,无法解开所有这些。所以让我们做一些实验吧。

如果&lt;、== 和&gt; 可以一致地处理操作数,那么&lt;=&gt; 也可以

感谢type juggling,PHP 中的大多数类型都可以与其他类型进行有意义的比较。无论在何种情况下,宇宙飞船操作员的行为方式都与&lt;、== 和&gt; 一致。

例如,让我们尝试使用一个字符串和一个 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 &lt;=&gt; $b 的结果正是文档所说的:-1 如果$a &lt; $b,0 如果$a == $b,1 如果$a &gt; $b。

但是如果&lt;、==和&gt;都没有返回true,那么spaceship就会混淆并返回1

虽然类型强制允许大多数不同类型的值相互比较,使得$a &lt; $b、$a == $b 和$a &gt; $b 中的一个为真,但仍有一些优势这不成立的情况。在这些情况下,$a &lt;=&gt; $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)

&lt;=&gt; 也可以抛出警告

如果我们将一个对象与一个 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)

无法比较的类型的结果显然是没有帮助的,并且会混淆任何期望宇宙飞船操作员一致地对不同类型的值进行排序的事情。因此,请勿在可能会进行此类无意义比较的情况下使用它。

【讨论】:

    猜你喜欢
    • 2015-06-10
    • 2021-08-07
    • 2011-03-04
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多