我正在阅读“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所说的,并且认为有左右列表操作符。所以现在我明白了它的含义,我理解了整个事情。
答案 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的方法来确保我们大多数时候不必添加括号。数学,按位运算符,比较,甚至正则表达式匹配具有更高的优先级。
做唯一具有较低优先级的内容是拼写出来的逻辑连接词and
,or
,xor
和not
。所以,如果我们写
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
评估为1
。 3 > 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 声明。假不是坏事。它的定义和打印都没有。