PHP 的 null 合并运算符的右关联性

Right associativity of PHP's null coalesce operator

提问人:SOFe 提问时间:10/5/2016 最后编辑:SOFe 更新时间:6/28/2022 访问量:602

问:

根据 PHP 文档,null 合并运算符是右关联的,即??

$a ?? $b ?? $c

相当于

$a ?? ($b ?? $c)

这有什么意义?对于开发人员来说,它是左关联还是右关联有什么区别吗?

对于那些认为它会调用更少函数的人来说,这是不正确的,因为根据我的测试,如果左操作数不为空,则不会计算右操作数:

function f(string $a) : string {
    echo "f($a)\n";
    return $a;
}
var_dump(f("a") ?? f("b") ?? f("c") ?? f("d"));
echo "===\n";
var_dump(((f("a") ?? f("b")) ?? f("c")) ?? f("d"));

输出:

f(a)
string(1) "a"
===
f(a)
string(1) "a"
PHP 运算符 null-coalescing-operator 关联性

评论

0赞 Rizier123 10/5/2016
如果 和 将是函数,那么如果它是左关联或右关联的,这将导致完全不同的执行,作为一个简单的例子。如果除此之外使用不同的运算符,则根据代码执行的“关联性”,也会发生同样的事情。$a$b$c??
0赞 deceze 10/5/2016
@Rizier123现在会吗?3v4l.org/PvvSr
0赞 deceze 10/5/2016
FWIW,我想不出任何一种情况,其中左关联运算符与堆叠运算符组合会产生不同的结果。它似乎只与内部短路有关;即,左关联运算符将始终计算所有堆叠表达式(即使不是它们的操作数),而不是尽快返回。不过,您可能会发现将其与其他运算符相结合的不同行为。??????
1赞 Dmitriy Lezhnev 7/20/2017
我要补充一点,“运算符优先级和关联性指定分组,但它们没有指定分组的执行顺序。gist.github.com/nikic/6699370

答:

-3赞 mister martin 10/5/2016 #1

这有什么意义?

与三元运算符(左关联)相比,右关联的零合并运算符允许堆叠。例如:

这是行不通的

echo isset($foo) ? $foo :
     isset($bar) ? $bar :
     isset($baz) ? $baz :
     'default';

这就是您可能期望三元运算符默认来自 C 或 C++ 的工作方式,但您错了。新运算符允许以下替代方法:??

这将起作用

echo $foo ?? $bar ?? $baz ?? 'default';

评论

1赞 SOFe 10/5/2016
如果它是左联想的,即有什么问题?(($foo ?? $bar) ?? $baz) ?? 'default'
0赞 mister martin 10/5/2016
@PEMapModder没什么问题,只是更干净/句法糖。
0赞 SOFe 10/5/2016
那么你就没有回答这个问题。“清洁剂/句法糖”似乎纯粹是基于意见的。
0赞 mister martin 10/5/2016
@PEMapModder你不必喜欢这个答案,但事实上,它就是答案。你问了意义,就提供了意义。
1赞 deceze 10/5/2016
OP 了解它的作用,并且它很容易堆叠,而不是 .问题是左派右派的关联性是否有任何实际区别。???:??
0赞 SOFe 10/5/2016 #2

我正在考虑性能问题,如果它是左关联的,你必须多次计算(如果第一个值为非 null),而只有当它是右关联时才计算一次。比较这两个案例:??

(("a" ?? "b") ?? "c") ?? "d"
"a" ?? ("b" ?? ("c" ?? "d"))

在第一行中,解析第二个(内)括号后,解析第一个(外)括号内的值,然后解析最后一个括号。 执行 3 次。?? "b"?? "c"?? "d"??

在第二行上,由于 is not null,则不需要解析整个块。 只执行一次。"a"("b" ?? ("c" ?? "d"))??

尽管右侧值未解析,但较少检查的次数可能仍然有益。!== null

(不过,我想知道这是否是唯一的原因?

0赞 Gordon 6/28/2022 #3

由于(左)操作数不必是定义的变量(包含替代的,即未定义的值),并且没有显式括号分组的多个(堆叠)合并表达式中最右边的一个操作数应该是“备份值”,在这种情况下,隐式右关联性的主要效果似乎是防止了未定义变量的警告。因此,对于所有根本没有(或根本不需要)定义的左操作数(最右边的)变量,这是正确(可接受的)。null

此代码没有使用括号进行显式分组,因此应用隐式右关联性

$a = $b ?? $c ?? $d;
echo $a;

输出

Warning: Undefined variable $d

因为所有操作数变量(包括最正确的“备份”)都是未定义的。$d

但是,此代码具有显式分组模拟左关联性

$a = ($b ?? $c) ?? $d;
echo $a;

输出

Warning: Undefined variable $c
Warning: Undefined variable $d

因为两个(所有)正确的操作数都被评估并被视为现有的“备份”值。

在这里查看:
https://3v4l.org/ZvTl9
https://3v4l.org/pEWk9