在 Perl 三元条件运算符中进行赋值会出现的问题

41

我的程序中这段Perl代码的输出结果不正确。

$condition ? $a = 2 : $a = 3 ;
print $a;
无论 $condition 的值是什么,输出总是 3,为什么?
5个回答

80

这在Perl的文档中有解释。

由于Perl运算符优先级的原因,该语句被解析为:

($condition ? $a= 2 : $a ) = 3 ;

由于 ?: 运算符会产生可分配的结果,因此 3 被赋值给条件的结果。

当 $condition 为 true 时,这意味着 ($a=2)=3,从而得到 $a=3。

当 $condition 为 false 时,这意味着 ($a)=3,从而得到 $a=3。

正确的写法是:

$a = ( $condition ? 2 : 3 );
print $a;

我们在工作中遇到了这个问题,所以我在这里发布希望能对其他人有所帮助。


1
当$condition为真时,这意味着$a=2=3,从而得到$a=3。我本以为$a=2=3会导致表达式语法错误或需要lvalue等错误...它究竟是如何被评估的? - Sundar R
你是对的,我会修改它。它应该是($a=2)=3而不是$a=2=3。 - Pat

41

一旦你有点感觉可能会遇到运算优先级的问题,一个解决方案是使用以下技巧来了解 Perl 认为你的意思:

perl -MO=Deparse,-p -e '$condition ? $a= 2 : $a= 3 ; print $a;'

在你的情况下,这将向你展示:

(($condition ? ($a = 2) : $a) = 3);
print($a);
-e syntax OK

...此时你应该会说“哦,原来是这样”!


Deparse是一个非常有趣的派对技巧。当然,一旦你怀疑存在优先级问题,通常你已经解决了大部分问题;-) - RET

22

仅仅是扩展之前的答案... 如果由于某种原因,赋值需要成为条件的一部分,你需要这样写:

$condition ? ($a=2) : ($a=3);

如果您需要根据条件分配不同的变量,这将非常有用。
$condition ? ($a=2) : ($b=3);

如果你正在选择变量,但无论如何都会分配相同的内容,你甚至可以这样做:

($condition ? $a : $b) = 3;

4
由于 Perl 运算符优先级,该语句被解析为:
($condition ? $a = 2 : $a ) = 3 ;

由于 ?: 运算符能够产生可赋值的结果,因此 3 被赋值给条件的结果。

当 $condition 为真时,这意味着 $a=2=3,从而得到 $a=3。

当 $condition 为假时,这意味着 $a=3,从而得到 $a=3。

正确的写法是:

$a = $condition ? 2 : 3;

通常情况下,你应该摆脱使用条件语句进行赋值的习惯,就像原例子中一样。这种做法会让 Perl 被认为是只能写不能读的语言。

一个好的经验规则是,条件语句仅适用于简单的值,而不是具有副作用表达式。当你或其他人需要在八个月后阅读这段代码时,你希望它看起来像这样吗?

$x < 3 ? foo($x) : bar($y);

或者像这样?
if ($x < 3) {
  $foo($x);
} else {
  $bar($y);
}

0

对Tithonium上面的答案有一个建议:

如果你想给同一个变量分配不同的值,这可能更好(copy-book方法):

$a = ($condition) ? 2 : 3;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接