鉴于代码:
my $x = 1; $x = $x * 5 * ($x += 5);
我希望$x
是180
:
$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)
在括号中,它应该是一个术语,因此首先执行,而不管表达式的顺序如何.
输入问题的行为给了我答案:术语具有最高优先级.这意味着,$x
在代码的第一个块被评估和产量1
,然后5
进行评估,产率5
,然后($x += 5)
是评估和产率6
(与设定的副作用$x
到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
每当我对这样的东西感到困惑时,我首先拔出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.