所以我有一些不起作用的代码:
print $userInput."\n" x $userInput2; #$userInput = string & $userInput2 is a integer
如果数字当然超过0,它会打印出来一次就好了,但是如果数字大于1,它就不会打印出来。我来自java背景,我认为它首先进行连接,那么结果将是与x
运算符相乘的结果。但当然不会发生这种情况。现在,当我执行以下操作时,它可以正常工作:
$userInput .= "\n";
print $userInput x $userInput2;
我是Perl的新手,所以我想了解链接到底发生了什么,如果我能做到的话。
答案 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
二进制“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;