【问题标题】:Nested Ternary-operator Associativity in php vs javaphp vs java中的嵌套三元运算符关联性
【发布时间】:2016-06-01 11:32:34
【问题描述】:

所以,我刚刚阅读了this blog post,我对“三元运算符是左关联”部分感到困惑,所以我在解释器中运行了示例代码:

$arg = 'T';
$vehicle = ( ( $arg == 'B' ) ? 'bus' :
             ( $arg == 'A' ) ? 'airplane' :
             ( $arg == 'T' ) ? 'train' :
             ( $arg == 'C' ) ? 'car' :
             ( $arg == 'H' ) ? 'horse' :
             'feet' );
echo $vehicle;

实际上,它返回 horse,这与博文中的反直觉相反。

出于好奇,然后我尝试通过重新编写它以适应我认为“左联想”想要的“使这项工作”。我明白了(格式很奇怪,但至少在我的脑海中更清楚了):

$arg = 'T';
$vehicle = ( ( $arg != 'B' ) ? 
                ( $arg != 'A' ) ? 
                    ( $arg != 'T' ) ? 
                        ( $arg != 'C' ) ? 
                            ( $arg != 'H' ) ? 
                                'feet' :
                            'horse' :
                        'car' :
                    'train' :
                'airplane' :
            'bus'
);
echo $vehicle;

现在,这可以按预期工作,因为任何字符 $arg 都会返回以该字符开头的车辆(当然是小写,但这在这里并不重要)。

仍然很好奇,因为我不清楚为什么前者不起作用,我想知道后者是否会在右关联语言中失败,因为它似乎不会。所以我在java解释器中测试了它。在这里为任何想要尝试并节省几秒钟的人编写代码。

class Main {
  public static void main(String[] args) {


    Character arg = 'a';
    String vehicle = ( ( arg == 'B' ) ? "bus" :
                        ( arg == 'A' ) ? "airplane" :
                        ( arg == 'T' ) ? "train" :
                        ( arg == 'C' ) ? "car" :
                        ( arg == 'H' ) ? "horse" :
                        "feet" );
    System.out.println(vehicle);
    vehicle = ( ( arg != 'B' ) ? 
                    ( arg != 'A' ) ? 
                        ( arg != 'T' ) ? 
                            ( arg != 'C' ) ? 
                                ( arg != 'H' ) ? 
                                "feet" :
                            "horse" :
                        "car" :
                    "train" :
                "airplane" :
            "bus"
    );
    System.out.println(vehicle);
  }
}

这两种格式都适用于 java。那么,php 中给出了什么?我听说它本质上是在评估领先的平等作为最后的平等 ($arg == 'H')。但如果是这样,那就意味着它的行为就像是

$vehicle = ((($arg == 'B') || ($arg == 'A') || ($arg == 'T') ||
             ($arg == 'C') || ($arg == 'H')) ? 'horse' : 'feet');

这对我来说没有意义。在我给出的第二个 php 示例中,我只移动了等式所在的位置,嵌套在三元表达式的 if true 部分,而不是 if false 部分。我不明白为什么如果第二种方法行得通,第一种方法行不通。这似乎更像是一个错误,而不是“它应该是这样工作的”,而且我只是误解了一些事情,我必须如此。

注意:我知道我可以将括号括起来以强制以我想要的方式评估表达式(这显然是右关联的)。我不是在寻找“如何使这项工作”,我想知道为什么它没有。

【问题讨论】:

    标签: java php ternary-operator


    【解决方案1】:

    左结合与右结合是关于将多个运算符串在一起时的优先级,例如A + B + C.

    对于三元运算符A ? B : C,这仅在额外的三元运算符替换C 部分(或A 部分)时才有意义:

    A ? B : X ? Y : Z
    (A ? B : X) ? Y : Z    <-- left-associative (PHP)
    A ? B : (X ? Y : Z)    <-- right-associative (Java, C, C++, C#, Perl)
    

    如果中间插入了多余的三元运算符(代替B),只能有一个意思:

    A ? X ? Y : Z : C
    A ? (X ? Y : Z) : C
    

    这就是为什么 PHP 和 Java 同意第二个的原因。没有应用左/右关联规则。

    【讨论】:

    • 哦,我想我明白了。由于X 不是0 或其他任何评估为false 的值,因此最终评估结果为Y。所以在第一种情况下,$arg=='B'false...$arg=='A'false。 ..$arg=='T'true...train 计算结果为true...car 计算结果为true...最终值为horse
    • @MiaoLiu 你明白了。 --- 结论:左结合三元运算符是一个非常糟糕的设计。或者总结一下linked blogPHP 是糟糕的设计。远离。
    • 所以这意味着,在 Java 中,嵌套最深的三元组首先被求值,然后该表达式的结果被用作外部表达式的返回值之一。然后将评估外部表达式并将其返回值用于下一个外部语句等。对吗?
    • @Ungeheuer 不完全是。不要混淆precedence and evaluation order
    猜你喜欢
    • 1970-01-01
    • 2016-07-19
    • 2011-10-29
    • 2021-04-14
    • 1970-01-01
    • 2013-01-21
    • 2011-09-07
    相关资源
    最近更新 更多