关于优先级+重复修饰符的问题

时间:2011-02-20 05:57:50

标签: perl operator-precedence

请你能解释一下这个显然不一致的行为:

use strict;
my @a;

print "a" x 2; # this prints: aa
@a = "a" x 2; print @a; # this prints: aa

print ("a") x 2; # this prints: a
@a = ("a") x 2; print @a; # this prints: aa

最后一个不应该打印一个'a'吗?

编辑:好的,现在这对我来说更有意义: “二进制”x“是重复运算符...在列表上下文中,如果左操作数括在括号中或者是由qw / STRING /形成的列表,则它会重复列表。” perlop

这对我来说很清楚(二进制x - 为什么使用二进制这个词?是否有一个否定的X?) 但无论如何: @a =(“a”)x 2#似乎在列表上下文中,因为我们在开头有一个数组 - 数组不是列表,但是它包含一个列表,所以我想我们可能有一个列表上下文,(不是数组上下文,尽管它们可能是同义词)。

我认为“左操作数”是(“a”)。 (或者是那个或@a)。 perlop没有说明操作数实际上是什么,查询perldoc.perl.org给出“找不到匹配”,谷歌搜索给出“在计算机编程中,操作数是用于描述任何能够被操纵的对象的术语”。就像数组一样。

所以左操作数可能会括在括号中,所以它可能会“重复列表”。该列表是:("a") x 2 或者是:("a")

如果我们重复("a") x 2,我们会得到("a") x 2 ("a") x 2。这似乎不对。

如果我们输入:print $a[1],我们会得到一个'a',所以“它重复列表”意味着Perl将("a") x 2变为("a", "a"),因此我们有效地获得了{{1} }

但是,@a=("a", "a")不会变成print ("a") x 2。那是因为print是一个具有高优先级的“列表运算符”。所以我们有效地得到:("a", "a")

数组是一个术语,因此它也具有高优先级,但@ a = stuff涉及赋值运算符=,它具有相对较低的优先级。所以它与印刷品完全不同。

3 个答案:

答案 0 :(得分:7)

在您的脚本中添加use warnings;,然后您将获得警告,如

print (...) interpreted as function .
Useless use of repeat (x) in void context .

print (("a") x 2);#这样打印:aa

正如您在评论中提到的,如何设置代码格式,我想说看 Perltidy

Perltidy 是一个Perl脚本,用于缩进和重新格式化Perl脚本以使其更易于阅读。如果你编写Perl脚本,或者花很多时间阅读它们,你可能会发现它很有用。

有关 Perltidy 的更多信息:

您可以下载perltidy并运行它 使用其默认值,或自定义它以使用您喜欢的支撑样式,缩进宽度等。

自定义很简单,并且有很多选项。默认值通常是一个很好的起点。

Perltidy还可用于生成代码的彩色HTML输出

Perltidy带有一套合理的默认值;但它们可能不适合你。幸运的是,您可以使用 tidyview 作为图形用户界面来预览perltidy对代码的更改,并查看哪些选项最适合您。您可以从CPAN下载tidyview

注意:始终在脚本开头添加use strictuse warnings

答案 1 :(得分:4)

我认为你得到奇怪行为的原因是因为perl的print命令是期望列表。引自relevant documentation

另外注意不要使用左括号跟随print关键字,除非你想要相应的右括号来终止print的参数;将括号括在所有参数周围。

放括号使它就像一个函数。考虑一下您是否执行此测试用例:

x("y") x 2;

sub x {
    my $y = shift;
    print "1: $y\n"; #result 1: y
    my $y = shift;
    print "2: $y\n"; #result 2:
}

当作为函数调用编写时,对于正在计算其参数的函数,结果是一致的,而不是在执行以下操作后正在计算的赋值。

答案 2 :(得分:3)

你被一个常见的Perl解析陷阱所困扰。您的第三个语句print ("a") x 2被解析为:

(print ("a")) x 2;

您可以添加另一组括号来修复解析:

print (("a") x 2);  # prints aa