5

给定代码:

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说得很清楚:

TERM 在 Perl 中具有最高优先级。它们包括变量、引号和类似引号的运算符、括号中的任何表达式,以及任何参数被括号括起来的函数。

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

4

4 回答 4

16

输入问题的行为给了我答案:术语具有最高优先级。这意味着$x第一块代码中的 被评估并产生1,然后5被评估并产生5,然后($x += 5)被评估并产生(具有设置为6的副作用):$x6

$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
于 2009-11-05T17:46:14.967 回答
9

每当我对这样的事情感到困惑时,我首先会拔出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。

于 2009-11-05T18:17:55.853 回答
4

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

于 2009-11-05T18:03:49.503 回答
2

运算符的结合性*是向左的,所以最左边的项总是在最右边的项之前计算。其他运算符,例如**右结合运算符,将($x += 5)在语句的其余部分之前进行评估。

于 2009-11-05T21:16:47.320 回答