Perl:优先级(左列表运算符)

2 perl

他在《Perl 编程》第 90 页中说道:

   @ary = (1, 3, sort 4, 2);
    print @ary;
Run Code Online (Sandbox Code Playgroud)

排序右侧的逗号在排序之前计算,而左侧的逗号在排序之后计算。...列表运算符倾向于吞噬..然后表现得像一个简单的术语”

  1. 赋值是否会导致排序被处理,或者在@ary通过打印扩展时会发生这种情况吗?
  2. 他说的那些“逗号”是什么意思?我的理解是,在赋值语句中,逗号的优先级低于列表运算符,因此排序首先运行并吞噬它的参数 (4 and 2)。逗号到底是如何被评估的?这样该语句就变成 (1, 3, 2, 4) 一个被分配的列表。逗号只是充当列表分隔符而不是运算符!事实上,在第 108 页,他说:不要将逗号的标量上下文使用与列表上下文使用混淆。
  3. 什么是向左和向右列表运算符?print @ary是向右列表运算符??那么它的优先级很低吗?

    打印($foo,退出);

这里,优先级是如何评估的?print 是一个列表运算符,看起来像一个函数,所以它应该首先运行!它有两个参数$fooexit..那么为什么 exit 不被视为字符串???毕竟优先级打印(列表运算符)具有更高的优先级?

print $foo, exit;
Run Code Online (Sandbox Code Playgroud)

在这里,您有 print 和 , 运算符,但列表运算符具有更高的优先级..所以.. exit 应该被视为字符串 - 为什么不呢?

   print ($foo & 255) + 1, "\n";
Run Code Online (Sandbox Code Playgroud)

在这里,因为它是一个列表运算符,所以它打印$foo & 255上面提到的exit东西不应该发生类似的事情吗?

Eri*_*rom 5

当对 Perl 如何解析构造有疑问时,您可以通过B::Deparse模块运行代码,这将从编译的内部表示生成 Perl 源代码。对于你的第一个例子:

$ perl -MO=Deparse,-p -e '@ary = (1, 3, sort 4, 2); print @ary;'
(@ary = (1, 3, sort(4, 2)));
print(@ary);
-e syntax OK
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,sort将两个参数放在右侧。

就执行顺序而言,您可以通过B::Concise模块找到它(我已添加注释):

$ perl -MO=Concise,-exec -e '@ary = (1, 3, sort 4, 2); print @ary;'
1  <0> enter 
2  <;> nextstate(main 1 -e:1) v:{
3  <0> pushmark s       # start of list
4  <$> const[IV 1] s    # 1 is added to list
5  <$> const[IV 3] s    # 3 is added to list
6  <0> pushmark s       # start of sort's argument list
7  <$> const[IV 4] s    # 4 is added to sort's argument list
8  <$> const[IV 2] s    # 2 is added to sort's argument list
9  <@> sort lK          # sort is run, and returns its list into the outer list
a  <0> pushmark s
b  <#> gv[*ary] s
c  <1> rv2av[t2] lKRM*/1
d  <2> aassign[t3] vKS/COMMON  # the list is assigned to the array
e  <;> nextstate(main 1 -e:1) v:{
f  <0> pushmark s         # start of print's argument list
g  <#> gv[*ary] s         # the array is loaded into print's argument list
h  <1> rv2av[t5] lK/1
i  <@> print vK           # print outputs it's argument list
j  <@> leave[1 ref] vKP/REFC
-e syntax OK
Run Code Online (Sandbox Code Playgroud)

对于第二个例子:

$ perl -MO=Deparse,-p -e 'print $foo, exit;'
print($foo, exit);
-e syntax OK

$ perl -MO=Concise,-exec -e 'print $foo, exit;'
1  <0> enter 
2  <;> nextstate(main 1 -e:1) v:{
3  <0> pushmark s
4  <#> gvsv[*foo] s   # add $foo to the argument list
5  <0> exit s         # call `exit` and add its return value to the list
6  <@> print vK       # print the list, but we never get here
7  <@> leave[1 ref] vKP/REFC
-e syntax OK
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,exit内置函数在尝试组装 的参数列表时运行print。由于exit导致程序退出,该print命令永远不会运行。

最后一个:

$ perl -MO=Deparse,-p -e 'print ($foo & 255) + 1, "\n";'
((print(($foo & 255)) + 1), '???');  # '???' means this was optimized away
-e syntax OK

$ perl -MO=Concise,-exec -e 'print ($foo & 255) + 1, "\n";'
1  <0> enter 
2  <;> nextstate(main 1 -e:1) v:{
3  <0> pushmark v
4  <0> pushmark s
5  <#> gvsv[*foo] s
6  <$> const[IV 255] s
7  <2> bit_and[t2] sK
8  <@> print sK
9  <$> const[IV 1] s
a  <2> add[t3] vK/2
b  <@> list vK
c  <@> leave[1 ref] vKP/REFC
-e syntax OK
Run Code Online (Sandbox Code Playgroud)