Perl究竟如何处理操作员链接?

时间:2013-03-03 05:57:42

标签: perl

所以我有一些不起作用的代码:

print $userInput."\n" x $userInput2; #$userInput = string & $userInput2 is a integer

如果数字当然超过0,它会打印出来一次就好了,但是如果数字大于1,它就不会打印出来。我来自java背景,我认为它首先进行连接,那么结果将是与x运算符相乘的结果。但当然不会发生这种情况。现在,当我执行以下操作时,它可以正常工作:

$userInput .= "\n";
print $userInput x $userInput2;

我是Perl的新手,所以我想了解链接到底发生了什么,如果我能做到的话。

3 个答案:

答案 0 :(得分:8)

您询问运算符优先级。 (“链接”通常是指方法调用的链接,例如$obj->foo->bar->baz。)

Perl文档页面perlop以优先级顺序列出所有运算符。 x具有与其他乘法运算符相同的优先级,.具有与其他加法运算符相同的优先级,因此当然首先计算x。 (即,它“具有更高的优先权”或“更紧密地结合”。)

与在Java中一样,您可以使用括号解决此问题:

print(($userInput . "\n") x $userInput2);

请注意,此处需要两个对括号。如果您只使用内括号,Perl会将它们视为指示print的参数,如下所示:

# THIS DOESN'T WORK
print($userInput . "\n") x $userInput2;

这将打印字符串一次,然后复制print的返回值多次。在(之前放置空格没有用,因为空格通常是可选的并被忽略。在某种程度上,这是运算符优先级的另一种形式:函数调用绑定比其他任何东西都紧密。

如果你真的讨厌括号多于严格必要的括号,你可以用一元+运算符击败Perl:

print +($userInput . "\n") x $userInput2;

这将print(分开,因此Perl知道该行的其余部分是单个表达式。一元+没有任何影响;它的主要用途就是这种情况。

答案 1 :(得分:4)

这是due to precedence of .(连接)运算符小于x运算符。所以它最终得到:

use strict;
use warnings;
my $userInput = "line";
my $userInput2 = 2;
print $userInput.("\n" x $userInput2);

输出:

line[newline]
[newline]

这就是你想要的:

print (($userInput."\n") x $userInput2);

打印出来:

line
line

答案 2 :(得分:3)

正如已经提到的,这是一个precedence问题,因为重复运算符x的优先级高于连接运算符.。然而,这并不是所有这一切,而且,问题本身来自一个糟糕的解决方案。

首先,当你说

print (($foo . "\n") x $count);

您正在做的是将重复运算符的上下文更改为列出上下文。

(LIST) x $count

上述陈述实际上意味着这一点(如果$count == 3):

print ( $foo . "\n", $foo . "\n", $foo . "\n" );  # list with 3 elements

来自perldoc perlop

  

二进制“x”是重复运算符。在标量上下文中,或者如果左操作数未括在括号中,则返回由左操作数组成的字符串,重复右操作数指定的次数。在列表上下文中,如果左操作数括在括号中或是由qw / STRING /形成的列表,则重复列表。如果右操作数为零或负数,则返回空字符串或空列表,具体取决于上下文。

解决方案按预期工作,因为print采用列表参数。但是,如果你有其他需要标量参数的东西,比如子程序:

foo(("text" . "\n") x 3);

sub foo {
    # @_ is now the list ("text\n", "text\n", "text\n");
    my ($string) = @_;   # error enters here
    # $string is now "text\n"
}

这是一个微妙的差异,可能并不总能产生预期的结果。

针对这种特殊情况的更好的解决方案是根本不使用连接运算符,因为它是多余的:

print "$foo\n" x $count;

甚至使用更普通的方法:

for (0 .. $count) {
    print "$foo\n";
}

或者

use feature 'say'
...
say $foo for 0 .. $count;