4

所以我有这段代码不起作用:

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

如果数字超过 0,它会打印一次,但如果数字大于 1,它不会打印出其余部分。我来自 java 背景,我假设它首先进行连接,然后结果将是与x运算符相乘的结果。当然,这不会发生。现在,当我执行以下操作时它可以工作:

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

我是 Perl 的新手,所以我想确切地了解链接是怎么回事,如果我能做到的话。

4

3 回答 3

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的返回值若干次。在 the 之前放置空格(并没有帮助,因为空格通常是可选的并且被忽略。在某种程度上,这是运算符优先级的另一种形式:函数调用比其他任何东西都绑定得更紧密。

如果你真的讨厌有比严格要求更多的括号,你可以用一元运算符打败 Perl +

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

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

于 2013-03-03T06:12:52.003 回答
4

这是由于 .(连接)运算符的优先级低于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
于 2013-03-03T06:12:24.437 回答
3

正如已经提到的,这是一个优先级问题,因为重复运算符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;   
于 2013-03-03T12:56:23.467 回答