8

我正在阅读“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";

但是,为什么第一个说法不一样呢?我认为这与打印的优先级有关。&& 的优先级高于打印,因此首先对其进行评估,然后再打印。而“and”的优先级低于 print,因此 6 > 3 将被打印,print 返回 1,然后用“and”计算。然而,这并没有真正的意义。

我已经阅读了有关列表运算符的优先级如何工作的 Perl 文档,但我仍然不理解这个示例。你们能剖析这两个语句,然后告诉我首先打印的是什么吗?您能否解释一下 Perl 文档中提到列表运算符为“左”和“右”时的含义?谢谢。


非常感谢大家的回答。我现在明白了。我确实在做cjm所说的,并认为有向左和向右的列表运算符。所以现在我明白了它的意思,我明白了整个事情。

4

3 回答 3

12

好的,对于初学者来说:列表运算符是 perl 中优先级最低的东西之一,但只在它们的右侧。你问这意味着什么:好吧,让我们让它变得简单。假设有一个名为 的列表foo。它做什么并不重要,但它就在那里。你可以很容易地创建这样一个东西,sub foo { map 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) );当然结束周围的括号仍然适用。

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

唯一具有较低优先级的事物是拼写出来的逻辑连接词and, or,xornot. 所以如果我们写

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是一个完全独立的逗号表达式——它什么都不做,因为它只是几个常量3 > 4"\n"在 void 上下文中评估。

于 2010-08-09T09:29:59.873 回答
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.

我不确定如何比文档更好地解释“向左”和“向右” 。但也许让您感到困惑的是,您认为存在“向左列表操作”和“向右列表操作”。这不是它的意思。它试图说列表运算符右侧的所有内容都被解释为该运算符的参数(除非您遇到了一个非常低优先级的布尔运算符,例如and)。但是列表运算符左侧的内容与该列表运算符无关。

于 2010-08-09T07:36:41.807 回答
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>4 是 undef声明。False 不是 undef。它已定义并且不打印任何内容。

于 2010-08-09T07:39:22.310 回答