奇数Perl条件运算符行为

war*_*rus 3 perl if-statement conditional-operator

我在Perl中做了一些工作,我使用条件运算符跑了一个奇怪的结果.

有问题的代码:

($foo eq "blah") ? @x = @somearray : @y = ("another","array");
Run Code Online (Sandbox Code Playgroud)

尝试编译此代码会导致错误" Assignment to both a list and a scalar at XXX line YY, near ');'".在尝试查明错误的来源时,我使用了几种不同的方式在Perl中表示数组,并且它们都返回相同的错误.现在起初我认为这对于赋值语句只是一些愚蠢的明显错误,但为了满足我的好奇心,我用更冗长的方式重写了语句:

if($foo eq "blah") {
    @x = @somearray;
} else {
    @y = ("another","array");
}
Run Code Online (Sandbox Code Playgroud)

该版本的代码编译得非常好.

在条件运算符的工作方式和基本的if-else语句之间是否存在一些很好的区别,我在这里缺少这些语句?我总是将条件运算符理解为第二个语句的简写版本.如果两者之间没有功能差异,为什么Perl会反对第一个语句,而不是第二个语句?

eph*_*ent 15

$ perl -MO=Deparse -e'($foo eq "blah") ? @x = @somearray : @y = ("another","array");'
Assignment to both a list and a scalar at -e line 1, near ");"
-e had compilation errors.
$foo eq 'blah' ? (@x = @somearray) : @y = ('another', 'array');
$ perl -MO=Deparse -e'($foo eq "blah") ? @x = @somearray : (@y = ("another","array"));'
$foo eq 'blah' ? (@x = @somearray) : (@y = ('another', 'array'));
-e syntax OK

注意括号:?:比紧更强=.

  • 虽然这就是Perl不喜欢代码的原因,但我认为错误的真正根源是滥用`?:`运算符. (6认同)

Ken*_*ack 9

Perl条件运算符应该是

$ variable =(表达式)?真正的作业:错误的作业;

你正在做什么看起来应该工作,并且与if/else语句基本相同.但与常规有所不同,有问题.


PP.*_*PP. 7

perlop中的文件明确规定,你应该把周围的赋值运算符的括号.

如果您不理解运算符优先级,则不使用括号是您自己的一根杆.不要为了自己的利益而过于聪明!

  • 我对"程序员"提出了激烈的争论,他们诋毁了使用括号的想法.如果您在头脑中保留一个运算符优先级表并且不定期切换语言,那就没问题.我已经编程了超过19年,我经常切换语言,知道不要对底层语言做出假设.此外,它意味着我可以以较低的风险移植表达式. (3认同)
  • 即使在优先级意味着它是多余的情况下,它也不会花费任何成本.我的经验法则是:如果你(或跟随你的程序员)在查看你的代码时必须考虑优先级,那么就要安全地使用它并使其明确.它也证明你已经考虑过这个问题了. (2认同)

Eth*_*her 6

这与你的问题有些正交,但它指出:Perl的条件运算符将上下文从第一个参数传播到第二个或第三个参数,所以这会给你带来不希望的结果:

$x = ($foo eq "blah") ? $somevalue : ("another","array");
Run Code Online (Sandbox Code Playgroud)

如果条件为假,$x则将分配一个整数值2(第三个参数中的元素数).

另一方面,如果您尝试执行纯粹的标量赋值:

# this is wrong, for the same order-of-operations reasons as with arrays
($foo eq "blah") ? $x = $somevalue : $x = "another value";
Run Code Online (Sandbox Code Playgroud)

这将是解决这种情况的合理(也是最佳)方式:

$x = ($foo eq "blah") ? $somevalue : "another value";
Run Code Online (Sandbox Code Playgroud)

同样,您可以通过以下方式优化原始代码:

@x = ($foo eq "blah") ? @somearray : ("another","array");
Run Code Online (Sandbox Code Playgroud)