Cha*_*ens 5 perl operator-precedence associativity
鉴于代码:
my $x = 1;
$x = $x * 5 * ($x += 5);
Run Code Online (Sandbox Code Playgroud)
我希望$x是180:
$x = $x * 5 * ($x += 5); #$x = 1
$x = $x * 5 * 6; #$x = 6
$x = 30 * 6;
$x = 180;
180;
Run Code Online (Sandbox Code Playgroud)
但相反,它是30; 但是,如果我更改条款的顺序:
$x = ($x += 5) * $x * 5;
Run Code Online (Sandbox Code Playgroud)
我明白了180.我感到困惑的原因是perldoc perlop非常清楚地说:
TERM在Perl中具有最高优先级.它们包括变量,引号和类似引号的运算符,括号中的任何表达式,以及其参数为括号的任何函数.
由于($x += 5)在括号中,它应该是一个术语,因此首先执行,而不管表达式的顺序如何.
Cha*_*ens 16
输入问题的行为给了我答案:术语具有最高优先级.这意味着,$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
Run Code Online (Sandbox Code Playgroud)
同样,第二个例子减少如下:
$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
Run Code Online (Sandbox Code Playgroud)
每当我对这样的东西感到困惑时,我首先拔出perldoc perlop,然后如果我仍然不确定,或者想看看特定的代码块是如何执行的,我使用B :: Deparse:
perl -MO=Deparse,-p,-q,-sC
my $x = 1;
$x = $x * 5 * ($x += 5);
Run Code Online (Sandbox Code Playgroud)
^D
得到:
(my $x = 1);
($x = (($x * 5) * ($x += 5)));
- syntax OK
Run Code Online (Sandbox Code Playgroud)
因此,在每个阶段替换值会给出:
($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;
Run Code Online (Sandbox Code Playgroud)
所以$ x暂时设置为6的事实并没有真正影响任何事情,因为较早的值(1)已经被替换为表达式,并且在表达式结束时它现在是30.