三元运算符左侧相关性

Kap*_*rma 37 php ternary-operator associativity

在PHP手册中,我在"操作员"下找到以下"用户提供的注释 ".

请注意,在php中,三元运算符?:具有左关联性,与C和C++不同,它具有正确的关联性.

你不能编写这样的代码(正如你在C/C++中习惯的那样):

<?php 
$a = 2; 
echo ( 
    $a == 1 ? 'one' : 
    $a == 2 ? 'two' : 
    $a == 3 ? 'three' : 
    $a == 4 ? 'four' : 'other'); 
echo "\n"; 
// prints 'four' 
Run Code Online (Sandbox Code Playgroud)

我实际上尝试它,它真的打印four.但是,我无法理解它背后的原因,仍然觉得它应该打印twoother.

有人可以解释一下这里发生了什么,为什么打印'四'?

200*_*ess 49

在任何理智的语言中,三元运算符是右关联的,因此您可以期望您的代码被解释为:

$a = 2;
echo ($a == 1 ? 'one' :
     ($a == 2 ? 'two' :
     ($a == 3 ? 'three' :
     ($a == 4 ? 'four' : 'other'))));    # prints 'two'
Run Code Online (Sandbox Code Playgroud)

但是,PHP三元运算符奇怪地是左关联的,因此您的代码实际上等效于此:

<?php
$a = 2;
echo (((($a == 1  ? 'one' :
         $a == 2) ? 'two' :
         $a == 3) ? 'three' :
         $a == 4) ? 'four' : 'other');   # prints 'four'
Run Code Online (Sandbox Code Playgroud)

如果仍不清楚,评估结果如下:

echo ((((FALSE    ? 'one' :
         TRUE)    ? 'two' :
         $a == 3) ? 'three' :
         $a == 4) ? 'four' : 'other');

echo ((( TRUE     ? 'two' :
         $a == 3) ? 'three' :
         $a == 4) ? 'four' : 'other');

echo ((  'two'    ? 'three' :
         $a == 4) ? 'four' : 'other');

echo (    'three' ? 'four' : 'other');

echo 'four';
Run Code Online (Sandbox Code Playgroud)

  • 我正确读到字符串被强制转换为布尔值吗?(如果是的话,哇.) (6认同)
  • @Wildcard:你正确地阅读它,这在PHP世界中是正常的.没有什么可震惊的:) (5认同)
  • @DianaHolland,但*之前的部分*?``是一个字符串. (3认同)

Ama*_*dan 21

因为你的整个表达式的评估就好像它一样(......) ? 'four' : 'other'.由于第一个元素可能是真正的东西,它给你'four'.在saner语言中,哪里?:有正确的关联性,整个表达式的评估就好像是$a == 1 ? 'one' : (......),如果$a不是1,你继续测试其他东西.

  • @NiettheDarkAbsol:在我看来,你应该为了可读性而加括号.在我看来,OP中的代码是完全清晰的,在一种理智的(非PHP)语言中,如果你使用括号,它实际上会变得更少. (15认同)
  • 嵌套的三元组太混乱了,所以我从不使用它们,有或没有括号.但答案很棒. (2认同)

Jon*_*hon 5

这就是我想出来的帮助自己理解三元运算符的左与右结合性的方法。

// PHP

$a = "T";
$vehicle =  $a == "B" ? "bus" :
            $a == "A" ? "airplane" :
            $a == "T" ? "train" :
            $a == "C" ? "car" :
            $a == "H" ? "horse" : "feet";

            // (as seen by the PHP interpreter)
            // INITIAL EXPRESSION: ((((($a == "B" ? "bus" : $a == "A") ? "airplane" : $a == "T") ? "train" : $a == "C") ? "car" : $a == "H") ? "horse" : "feet");
            // STEP 1:             (((((FALSE ? "bus" : FALSE) ? "airplane" : TRUE) ? "train" : FALSE) ? "car" : FALSE) ? "horse" : "feet")
            // STEP 2:             ((((FALSE ? "airplane" : TRUE) ? "train" : FALSE) ? "car" : FALSE) ? "horse" : "feet")
            // STEP 3:             (((TRUE ? "train" : FALSE) ? "car" : FALSE) ? "horse" : "feet")
            // STEP 4:             (("train" ? "car" : FALSE) ? "horse" : "feet")
            // STEP 5:             ("car" ? "horse" : "feet")
            // FINAL EVALUATION:   ("horse")

            // If you used the initial expression here (with the parenthesis) in a different language, it would also evaluate to "horse."

echo $vehicle; // gives us "horse"
Run Code Online (Sandbox Code Playgroud)

这与:

// EVERY OTHER LANGUAGE

var a = "T";
var vehicle =   a == "B" ? "bus" :
                a == "A" ? "airplane" :
                a == "T" ? "train" :
                a == "C" ? "car" :
                a == "H" ? "horse" : "feet";

                // (as seen by the other language's interpreter)
                // INITIAL EXPRESSION: (a == "B" ? "bus" : (a == "A" ? "airplane" : (a == "T" ? "train" : (a == "C" ? "car" : (a == "H" ? "horse" : "feet")))));
                // STEP 1:             (FALSE ? "bus" : (FALSE ? "airplane" : (TRUE ? "train" : (FALSE ? "car" : (FALSE ? "horse" : "feet")))))
                // STEP 2:             (FALSE ? "bus" : (FALSE ? "airplane" : (TRUE ? "train" : (FALSE ? "car" : "feet"))))
                // STEP 3:             (FALSE ? "bus" : (FALSE ? "airplane" : (TRUE ? "train" : "feet")))
                // STEP 4:             (FALSE ? "bus" : (FALSE ? "airplane" : "train"))
                // STEP 5:             (FALSE ? "bus" : "train")
                // FINAL EVALUATION:   ("train")

                // If you used the initial expression here (with the parenthesis) in PHP, it would also evaluate to "train."

console.log(vehicle); // gives us "train"
Run Code Online (Sandbox Code Playgroud)

如果您注意到,在 PHP 示例中,最里面的表达式在左侧,而在第二个示例中,最里面的表达式在右侧。每一步都计算下一个最里面的表达式,直到有一个结果。如果您要在 PHP 中嵌套三元运算,括号显然非常重要!

  • 我不认为你对“所有其他语言”的表述是正确的。根据我的理解,大多数问题都会延迟计算条件运算符的最后 2 个子表达式,因此许多表达式永远不会被计算。 (2认同)