【问题标题】:Right associativity of PHP's null coalesce operatorPHP 的空合并运算符的右结合性
【发布时间】:2017-02-13 23:47:37
【问题描述】:

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

$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"

【问题讨论】:

  • 如果 $a$b$c 是函数,那么如果它是左关联或右关联作为一个简单的示例,这将导致完全不同的执行。如果您在 ?? 之外使用不同的运算符,那么会发生同样的事情,具体取决于代码执行的“关联性”完全不同。
  • @Rizier123 现在可以吗? 3v4l.org/PvvSr
  • FWIW,我想不出任何左关联 ?? 运算符与堆叠的 ?? 运算符组合会产生不同结果的情况。它似乎只与内部短路有关;即左关联 ?? 运算符将始终评估所有堆叠的表达式(即使不是它们的操作数),而不是尽快返回。不过,您可能会发现将它与其他运算符结合使用会产生不同的行为。
  • 我会添加“运算符优先级和关联性指定分组,但它们没有指定执行组的顺序。” gist.github.com/nikic/6699370

标签: php operators null-coalescing-operator associativity


【解决方案1】:

我正在考虑性能问题,如果?? 是左关联的,则必须多次评估(如果第一个值不为空),而仅在它是右关联的情况下评估一次。比较这两种情况:

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

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

在第二行,由于"a" 不为空,所以不需要解析("b" ?? ("c" ?? "d")) 的整个块。 ?? 只执行一次。

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

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

【讨论】:

    【解决方案2】:

    这有什么意义?

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

    这行不通

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

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

    这会起作用

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

    【讨论】:

    • 如果它是左关联的,即(($foo ?? $bar) ?? $baz) ?? 'default',有什么问题?
    • @PEMapModder 没有错,它只是更清洁/语法糖。
    • 那你没有回答这个问题。 “清洁剂/语法糖”似乎纯粹是基于意见的。
    • @PEMapModder 你不必喜欢这个答案,但事实上它就是答案。你问意义,意义就提供了。
    • OP 了解 ?? 的作用,并且与 ?: 相比,它易于堆叠。问题是??leftright associativity 是否有任何实际区别。
    猜你喜欢
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    • 2019-03-01
    • 1970-01-01
    • 2011-11-08
    • 2012-09-19
    • 1970-01-01
    • 2013-09-13
    相关资源
    最近更新 更多