当前位置:  开发笔记 > 编程语言 > 正文

Perl如何决定在表达式中评估术语的顺序?

如何解决《Perl如何决定在表达式中评估术语的顺序?》经验,为你挑选了2个好方法。

鉴于代码:

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)在括号中,它应该是一个术语,因此首先执行,而不管表达式的顺序如何.



1> Chas. Owens..:

输入问题的行为给了我答案:术语具有最高优先级.这意味着,$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


正确.绊倒你的不是优先权,而是评价的顺序.直到第一次乘法发生后才会计算`($ x + = 5)`.括号仅用于确保在第二次乘法之前发生`+ =`.在这种情况下,这可以防止语法错误,因为乘法具有比赋值更高的优先级,并且乘法的结果不是有效的左值.

2> Ether..:

每当我对这样的东西感到困惑时,我首先拔出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.


`*`是一个从左到右计算的二元运算符,所以`$ x*$ y*$ z`将计算为`(($ x*$ y)*$ z)`.
推荐阅读
N个小灰流_701
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有