在Perl中列出运算符优先级

时间:2010-08-09 07:04:17

标签: perl operator-precedence

我正在阅读“Beginning Perl”一书,它给出了这两个陈述:

print "Test one: ", 6 > 3 && 3 > 4, "\n";
print "Test two: ", 6 > 3 and 3 > 4, "\n";

第一行不使用新行打印,第二行打印1,没有新行。

我对输出感到困惑。根据作者的说法,第二个语句给出了奇怪的输出,因为它就像是说:

print ("Test two: ", 6 > 3) and 3 > 4, "\n";

但是,为什么第一个陈述不一样?我认为它与print的优先级有关。和&&优先级高于打印优先级,因此首先进行评估,然后打印。而“和”的优先级低于打印,因此6>将打印3,打印返回1,然后用“和”评估。然而,这并没有多大意义。

我已经阅读了关于优先级如何对列表运算符起作用的Perl文档,但我仍然不理解这个例子。你们可以剖析这两个陈述,告诉我先打印什么吗?您是否也可以解释Perl文档在提到列表操作符为“向左”和“向右”时的含义?感谢。


非常感谢大家的回答。我现在明白了。我确实在做cjm所说的,并且认为有左右列表操作符。所以现在我明白了它的含义,我理解了整个事情。

3 个答案:

答案 0 :(得分:12)

好的,对于初学者:list-operators是perl中优先级最低的东西,但仅在右侧。你问这意味着什么:好吧,让我们简单一点。假设有一个名为foo的listop。它的作用并不重要,但它就在那里。你可以使用sub foo { map 10 * $_, @_ }轻松创建这样的东西,它返回每个参数乘以10。那就是:

print 1, 2, 3;相当于print( 1, 2, 3 );
print foo 1, 2, 3;相当于print( foo( 1, 2, 3 ) );
print 1, foo 2, 3;相当于print( 1, foo( 2, 3 ) );

我们可以看到foo在右侧尽可能地吞噬 - 只有声明的结尾(到目前为止......)才能阻止它。如果我们写的@array = (1, foo 2, 3);等同于@array = (1, foo(2, 3) );,因为当然结束周围的括号仍然适用。

由于逗号也是非常低的优先级(就在“List运算符(向右)”之上),我们也可以将我们想要的任何类型的表达式放入listop的参数中 - 这只是perl的方法来确保我们大多数时候不必添加括号。数学,按位运算符,比较,甚至正则表达式匹配具有更高的优先级。

唯一具有较低优先级的内容是拼写出来的逻辑连接词andorxornot 。所以,如果我们写

foo 1, 2, 3 and 4;

表示(foo(1, 2, 3) and 4) - foo的参数停在and的左侧。在一个人为的例子中,这似乎很愚蠢,所以让我们把它变成一个常见的perl习语:

open $fh, '<', $filename or die "$! opening $filename";

相当于

(open($fh, '<', $filename) or die("$! opening $filename"));

实际上完全等同于(并编译成)

die "$! opening $filename" unless open $fh, '<', $filename;

使用unless的语句修饰符形式(根本不是运算符,每个语句只允许使用一次,并且仅在语句结束时使用,因此它不会真正参与优先级,但您可以将其视为“低于最低”优先级向左)。

所以,无论如何,返回原始代码示例 - print的参数在and左侧结束,and右侧是完全独立的逗号表达式 - 什么都不做,因为它只是在void上下文中评估的几个常量3 > 4"\n"

答案 1 :(得分:8)

以下是完整括号中这些陈述的外观:

print("Test one: ", ((6 > 3) && (3 > 4)), "\n");
print("Test two: ", (6 > 3)) and ((3 > 4), "\n");

>具有最高优先级,然后是&&,然后是,,然后是print,然后是and

6 > 3评估为13 > 4的计算结果为false,在Perl中,它是一个特殊值,在数字上下文中为0,但在字符串上下文中为空字符串(如此处)。所以((6 > 3) && (3 > 4))产生空字符串。

因此,第一个语句将3个参数传递给print"Test one: ",空字符串和换行符。它按顺序打印每个参数。

第二个语句只将2个参数传递给print"Test two: "1。换行不会被打印,因为它从未传递给print

我不确定如何比the docs更好地解释“向左”和“向右”。但也许令你困惑的是,你认为有“向左列表操作”和“向右列表操作”。这不是它的意思。它试图说明列表运算符右侧的所有内容都被解释为该运算符的参数(除非您点击其中一个非常低优先级的布尔运算符,如and)。但是列表运算符左侧的内容与该列表运算符没有关联。

答案 2 :(得分:4)

正如你所说,除了“这没有意义”之外。

第一个是

print "Test one: ", (6 > 3 && 3 > 4), "\n";

和第二个

(print "Test two: ", 6 > 3) and (3 > 4, "\n");

如果您打开警告(use warnings),则会收到警告Useless use of a constant in void context,因为and的右侧会评估包含元素 false 的列表,换行,但从未使用过。

修改:更正了我的 3&gt; 4是undef 声明。假不是坏事。它的定义和打印都没有。