来自Programming Perl pg 90,他说:
@ary = (1, 3, sort 4, 2);
print @ary;
排序右侧的逗号在排序之前进行评估,但左侧的逗号在之后进行评估。 ...列表操作员倾向于狼吞虎咽......然后就像一个简单的术语“
@ary
时是否会发生这种情况?(4 and 2)
..如何对逗号进行评估?因此,statemnent变为(1,3,2,4)一个被分配的列表..逗号只是作为列表分隔符而不是操作符!!事实上,在pg:108中他说:不要混淆逗号的标量上下文使用和列表上下文使用.. 什么是向左和向右列表运算符? print @ary
是一个向右列表操作符??它的优先级非常低?
print($ foo,exit);
这里,如何评估优先级? print是一个看起来像函数的列表运算符,所以它应该先运行!它有两个参数$foo
和exit
..那么为什么exit不被视为字符串???在所有优先级打印(列表运算符)具有更高优先级后
print $foo, exit;
这里,你有打印和运算符,但列表运算符具有更高的优先级..所以.. exit应该被视为一个字符串 - 为什么不呢?
print ($foo & 255) + 1, "\n";
这里因为它是一个列表运算符,它打印$foo & 255
不应该与上面提到的exit
东西发生类似的事情。
答案 0 :(得分:3)
sort
在被调用时被评估,它实际上与赋值没有任何关系。 sort
返回一个列表。所以你要分配的是:
@ary =(1,3,(2,4));
Perl会忽略第二个括号,因此您最终会得到1,3,2,4
。
您所指的逗号不再存在。这是排序的第二个参数。 Perl将您的列表视为3项列表而不是4项列表(在分配中将其扩展为4)
向右执行某些参数(例如打印出来或存储它们),向左做参数,通常是通过修改它们。
print
的行为与Perl中的任何其他函数(或我曾用过的任何其他语言)相同。如果将函数作为参数调用,则该函数的返回值将作为参数给出。你的情况如下:
print ($foo, exit);
或同等(parens无所谓)
print $foo, exit;
什么都不做,因为你要求它打印退出的返回值。您的程序会先退出,这样您就什么也得不到了。我不明白为什么你希望exit
被视为一个字符串。除非你引用它,否则exit
在所有情境中都是一个函数。
print ($foo & 255) + 1,"\n";
来自perlop
给出了这个例子:
乍一看可能没有达到预期效果。括号 将“print”的参数列表括起来(打印出来) “$ foo& 255”的结果。然后将一个添加到返回值 “打印”(通常为1)。结果是这样的:
1 + 1, "\n"; # Obviously not what you meant.
要做正确的意思,你必须写下:
print(($foo & 255) + 1, "\n");
答案 1 :(得分:3)
如果对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
正如您所看到的,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
对于你的第二个例子:
$ 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
正如您所看到的,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
答案 2 :(得分:0)
不确定以下内容是否完全准确(这是来自IRC的混搭,上述答案,谷歌以及我对该书的解释)
(运算符)(操作数)这被视为向左运算符,因为它位于操作数的左侧。 (操作数)(运算符)这被视为向右运算符,因为它位于操作数的右侧。所以,(1,2,3,排序4,5,排序6,7)这里第二种排序,既可作为左操作员,也可作为右操作员! sort 6,7是(6,7)左边的左字 - 它是操作数。这也是排序的权利(4,5,所以这里是正确的,优先级非常低。
@ary =(1,3,排序4,2); print @ary;
这里,sort是一个向左的列表运算符,所以它的优先级最高,而且'Cfreak'表示..
这里,打印是向左列表,所以最高优先级,所以它应该首先执行但是!执行它应该解决它的参数和裸字'退出'。要解决它,我想它会运行退出,ergo ..打印$ foo,...将吞噬所有它的参数然后它必须处理它们并在裸字运行它..
非常感谢你们!