奇怪的 Perl 条件运算符行为

发布于 2024-08-11 04:40:04 字数 572 浏览 10 评论 0原文

我正在 Perl 中做一些工作,并且使用条件运算符遇到了一个奇怪的结果。

有问题的代码:

($foo eq "blah") ? @x = @somearray : @y = ("another","array");

尝试编译此代码会导致错误“在 XXX 行 YY 处对列表和标量进行赋值,靠近 ');'”。在尝试查明错误来源时,我使用几种不同的方式在 Perl 中表示数组来编写此代码,它们都返回相同的错误。现在,起初我认为这只是赋值语句中的一些愚蠢的明显错误,但为了满足我的好奇心,我以更详细的方式重写了该语句:

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

该版本的代码编译得很好。

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

I'm doing some work in Perl and I ran across an odd result using the conditional operator.

The code in question:

($foo eq "blah") ? @x = @somearray : @y = ("another","array");

Trying to compile this code results in the error "Assignment to both a list and a scalar at XXX line YY, near ');'". In trying to pinpoint the source of the error I've written this using a couple different ways of representing an array in Perl and they all return with the same error. Now at first I thought it was just some dumb obvious mistake with the assignment statements, but just to satisfy my curiosity I rewrote the statement in a more verbose way:

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

That version of the code compiled perfectly fine.

Is there some fine distinction between how the conditional operator works and a basic if-else statement works that I'm missing here? I always understood the conditional operator to be just a short-hand version of the second statement. If there isn't a functional difference between the two, why would Perl object to the first statement, but not the second?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

白云不回头 2024-08-18 04:40:04
$ 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 -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

Note the parentheses: ?: binds tighter than =.

长发绾君心 2024-08-18 04:40:04

Perl 条件运算符是

$variable = (expression) ?真分配:假分配;

您正在做的事情看起来应该可行,并且与 if/else 语句基本相同。但与正常情况的差异足以产生问题。

The Perl conditional operator is meant to be

$variable = (expression) ? true assignment : false assignment;

What you're doing looks like it should work and is basically the same as the if/else statement. But is just different enough from the norm to have issues.

や莫失莫忘 2024-08-18 04:40:04

perlop 文档明确指出您应该在赋值运算符两边加上括号。

如果您不了解运算符的优先级,那么不使用括号就是自取其辱。不要再为了自己的利益而变得太聪明了!

The perlop documentation clearly states you should put parentheses around assignment operators.

Failing to use parentheses is a rod for your own back if you don't understand operator precedence. Stop trying to be too smart for your own good!

云仙小弟 2024-08-18 04:40:04

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

$x = ($foo eq "blah") ? $somevalue : ("another","array");

如果条件为 false,则 $x 将被分配单个整数值 2 (第三个参数中的元素数量)。

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

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

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

$x = ($foo eq "blah") ? $somevalue : "another value";

同样,您可以这样优化原始代码:

@x = ($foo eq "blah") ? @somearray : ("another","array");

This is somewhat orthogonal to your question, but it bears pointing out: Perl's conditional operator propagates context from the first argument down into the second or third arguments, so this would give you undesired results:

$x = ($foo eq "blah") ? $somevalue : ("another","array");

If the conditional were false, $x would instead be assigned a single integer value 2 (the number of elements in the third argument).

If on the other hand you were attempting to perform a purely scalar assignment:

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

This would be a reasonable (and the best) way to resolve the situation:

$x = ($foo eq "blah") ? $somevalue : "another value";

Likewise, you could optimize your original code this way:

@x = ($foo eq "blah") ? @somearray : ("another","array");
牵你的手,一向走下去 2024-08-18 04:40:04

这将是使用优先级较低的“and”和“or”运算符的好地方。

$foo eq 'blah' and @x = @somearray or @y = ('another', 'array');

前提是您确定 @x = @somearray 始终为真。或者你可以把它们翻转过来。

This would be a good spot to use the lower precedence 'and' and 'or' operators.

$foo eq 'blah' and @x = @somearray or @y = ('another', 'array');

provided you are sure that @x = @somearray will always be true. or you could flip them around.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文