Perl 如何决定计算表达式中的项的顺序?

发布于 2024-08-10 08:47:37 字数 679 浏览 5 评论 0原文

给定代码:

my $x = 1;

$x = $x * 5 * ($x += 5);

我希望 $x180

$x = $x * 5 * ($x += 5); #$x = 1
$x = $x * 5 * 6;         #$x = 6
$x = 30 * 6;
$x = 180;
180;

但实际上它是 30;但是,如果我更改术语的顺序:

$x = ($x += 5) * $x * 5;

我会得到180。我感到困惑的原因是 perldoc perlop 说得非常清楚:

术语在 Perl 中具有最高优先级。它们包括变量, 引用和类引用运算符、括号中的任何表达式以及任何 其参数带括号的函数。

由于 ($x += 5) 在括号中,因此它应该是一个术语,因此首先执行,无论表达式的顺序如何。

Given the code:

my $x = 1;

$x = $x * 5 * ($x += 5);

I would expect $x to be 180:

$x = $x * 5 * ($x += 5); #$x = 1
$x = $x * 5 * 6;         #$x = 6
$x = 30 * 6;
$x = 180;
180;

But instead it is 30; however, if I change the ordering of the terms:

$x = ($x += 5) * $x * 5;

I do get 180. The reason I am confused is that perldoc perlop says very plainly:

A TERM has the highest precedence in Perl. They include variables,
quote and quote-like operators, any expression in parentheses, and any
function whose arguments are parenthesized.

Since ($x += 5) is in parentheses, it should be a term, and therefore executed first, regardless of the ordering of the expression.

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

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

发布评论

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

评论(4

厌味 2024-08-17 08:47:37

输入问题的行为给了我答案:术语具有最高优先级。这意味着第一段代码中的 $x 被求值并产生 1,然后 5 被求值并产生 5< /code>,然后对 ($x += 5) 进行求值并产生 6 (将 $x 设置为 $x 会产生副作用code>6):

$x = $x * 5 * ($x += 5);
address of $x = $x * 5 * ($x += 5); #evaluate $x as an lvalue
address of $x = 1 * 5 * ($x += 5);  #evaluate $x as an rvalue
address of $x = 1 * 5 * ($x += 5);  #evaluate 5
address of $x = 1 * 5 * 6;          #evaluate ($x += 5), $x is now 6
address of $x = 1 * 5 * 6;          #evaluate 1 * 5
address of $x = 5 * 6;              #evaluate 1 * 5
address of $x = 30;                 #evaluate 5 * 6
30;                                 #evaluate address of $x = 30

同样,第二个示例如下所示:

$x = ($x += 5) * $x * 5; 
address of $x = ($x += 5) * $x * 5; #evaluate $x as an lvalue
address of $x = 6 * $x * 5;         #evaluate ($x += 5), $x is now 6
address of $x = 6 * 6 * 5;          #evaluate $x as an rvalue
address of $x = 6 * 6 * 5;          #evaluate 5
address of $x = 36 * 5;             #evaluate 6 * 6
address of $x = 180;                #evaluate 36 * 5
180;                                #evaluate $x = 180

The act of typing out the question yielded the answer to me: terms have the highest precedence. That means that the $x in the first chunk of code is evaluated and yields 1, then 5 is evaluated and yields 5, then ($x += 5) is evaluate and yields 6 (with a side-effect of setting $x to 6):

$x = $x * 5 * ($x += 5);
address of $x = $x * 5 * ($x += 5); #evaluate $x as an lvalue
address of $x = 1 * 5 * ($x += 5);  #evaluate $x as an rvalue
address of $x = 1 * 5 * ($x += 5);  #evaluate 5
address of $x = 1 * 5 * 6;          #evaluate ($x += 5), $x is now 6
address of $x = 1 * 5 * 6;          #evaluate 1 * 5
address of $x = 5 * 6;              #evaluate 1 * 5
address of $x = 30;                 #evaluate 5 * 6
30;                                 #evaluate address of $x = 30

Similarly, the second example reduces like this:

$x = ($x += 5) * $x * 5; 
address of $x = ($x += 5) * $x * 5; #evaluate $x as an lvalue
address of $x = 6 * $x * 5;         #evaluate ($x += 5), $x is now 6
address of $x = 6 * 6 * 5;          #evaluate $x as an rvalue
address of $x = 6 * 6 * 5;          #evaluate 5
address of $x = 36 * 5;             #evaluate 6 * 6
address of $x = 180;                #evaluate 36 * 5
180;                                #evaluate $x = 180
℡Ms空城旧梦 2024-08-17 08:47:37

每当我对这样的事情感到困惑时,我首先会拿出 perldoc perlop,然后如果我仍然不确定,或者想查看特定代码块将如何执行,我使用 B:: Deparse:

perl -MO=Deparse,-p,-q,-sC
my $x = 1;
$x = $x * 5 * ($x += 5);

^D

给出:

(my $x = 1);
($x = (($x * 5) * ($x += 5)));
- syntax OK

所以在每个阶段替换值给出:

($x = (($x * 5) * ($x += 5)));
($x = ((1 * 5) * ($x += 5)));
($x = ((5) * (6))); # and side-effect: $x is now 6
($x = (5 * 6));
($x = (30));
($x = 30);
$x = 30;

所以 $x 暂时设置为 6 的事实并没有真正影响任何东西,因为早期的值 (1)已经代入表达式中,到表达式结束时,它现在是 30。

Whenever I have confusion about stuff like this I first pull out perldoc perlop, and then if I'm still not sure, or want to see how a particular block of code will get executed, I use B::Deparse:

perl -MO=Deparse,-p,-q,-sC
my $x = 1;
$x = $x * 5 * ($x += 5);

^D

gives:

(my $x = 1);
($x = (($x * 5) * ($x += 5)));
- syntax OK

So substituting values at each stage gives:

($x = (($x * 5) * ($x += 5)));
($x = ((1 * 5) * ($x += 5)));
($x = ((5) * (6))); # and side-effect: $x is now 6
($x = (5 * 6));
($x = (30));
($x = 30);
$x = 30;

So the fact that $x was temporarily set to 6 doesn't really affect anything, because the earlier value (1) was already substituted into the expression, and by the end of the expression it is now 30.

无人问我粥可暖 2024-08-17 08:47:37

$x 本身也是一个术语。由于首先遇到它(在您的第一个示例中),因此首先对其进行评估。

$x by itself is also a TERM. Since it is encountered first (in your first example), it is evaluated first.

扎心 2024-08-17 08:47:37

* 运算符的结合性是向左的,因此最左边的项总是在最右边的项之前计算。其他运算符(例如 **)是右关联的,并且会在语句的其余部分之前计算 ($x += 5)

The associativity of the * operator is leftward, so the left most term is always evaluated before the right most term. Other operators, such as ** are right associative and would have evaluated ($x += 5) before the rest of the statement.

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