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

时间:2011-02-17 17:47:56

标签: perl

来自Programming Perl pg 90,他说:

   @ary = (1, 3, sort 4, 2);
    print @ary;

排序右侧的逗号在排序之前进行评估,但左侧的逗号在之后进行评估。 ...列表操作员倾向于狼吞虎咽......然后就像一个简单的术语“

  1. 分配是否会导致排序正在处理,或者在通过打印扩展@ary时是否会发生这种情况?
  2. 所有“逗号”的东西是什么意思?我的理解是,在赋值语句中,逗号的优先级低于列表运算符,因此sort先运行并吞噬它的参数(4 and 2) ..如何对逗号进行评估?因此,statemnent变为(1,3,2,4)一个被分配的列表..逗号只是作为列表分隔符而不是操作符!!事实上,在pg:108中他说:不要混淆逗号的标量上下文使用和列表上下文使用..
  3. 什么是向左和向右列表运算符? print @ary是一个向右列表操作符??它的优先级非常低?

    print($ foo,exit);

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

    print $foo, exit;
    

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

       print ($foo & 255) + 1, "\n";
    

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

3 个答案:

答案 0 :(得分:3)

  1. sort在被调用时被评估,它实际上与赋值没有任何关系。 sort返回一个列表。所以你要分配的是:

    @ary =(1,3,(2,4));

  2. Perl会忽略第二个括号,因此您最终会得到1,3,2,4

    1. 您所指的逗号不再存在。这是排序的第二个参数。 Perl将您的列表视为3项列表而不是4项列表(在分配中将其扩展为4)

    2. 向右执行某些参数(例如打印出来或存储它们),向左做参数,通常是通过修改它们。

    3. 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. (运算符)(操作数)这被视为向左运算符,因为它位于操作数的左侧。 (操作数)(运算符)这被视为向右运算符,因为它位于操作数的右侧。所以,(1,2,3,排序4,5,排序6,7)这里第二种排序,既可作为左操作员,也可作为右操作员! sort 6,7是(6,7)左边的左字 - 它是操作数。这也是排序的权利(4,5,所以这里是正确的,优先级非常低。

  2. 2。

    @ary =(1,3,排序4,2);     print @ary;

    这里,sort是一个向左的列表运算符,所以它的优先级最高,而且'Cfreak'表示..

    1. print($ foo,exit);打印$ foo,退出;
    2. 这里,打印是向左列表,所以最高优先级,所以它应该首先执行但是!执行它应该解决它的参数和裸字'退出'。要解决它,我想它会运行退出,ergo ..打印$ foo,...将吞噬所有它的参数然后它必须处理它们并在裸字运行它..

      1. 打印($ foo&amp; 255)与上述相同。 print获得最高优先权,但它现在需要解决它的各种参数..所以$ foo&amp; 255等'Cfreak'解释。
      2. 非常感谢你们!