【问题标题】:How exactly does Perl handle operator chaining?Perl 究竟是如何处理运算符链的?
【发布时间】:2013-03-03 20:56:23
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: perl


    【解决方案1】:

    您在询问运算符优先级。 (“链接”通常是指方法调用的链接,例如$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 知道该行的其余部分是单个表达式。一元 + 没有任何作用;它的主要用途正是这种情况。

    【讨论】:

    • 哇哦。非常感谢您的解释。实际上,我确实尝试了括号,就像您预期的那样它是错误的,因为它只有一对。但我以为我理解 Perl 运算符的优先级。猜不到!
    • print "$userInput\n" x $userInput2
    【解决方案2】:

    这是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
    

    【讨论】:

    • x 具有更高的优先级。优先级更高。
    【解决方案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;   
    

    【讨论】:

      猜你喜欢
      • 2011-12-31
      • 2020-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-04
      • 1970-01-01
      • 2010-12-24
      • 2016-04-08
      相关资源
      最近更新 更多