4

だから私は動作しないコードのこのビットを持っています:

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

もちろん、数値が 0 を超える場合は 1 回は問題なく出力されますが、数値が 1 より大きい場合は残りは出力されません。結果は、演算子で自分自身を乗算するものになります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);

ここでは2組の括弧が必要であることに注意してください。内側の括弧のみを使用した場合、Perlはそれらを次のprintようにへの引数を示すものとして扱います。

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

これにより、文字列が1回出力されprint、その後、の戻り値が数回複製されます。空白は一般にオプションであり無視されるため、の前にスペースを(入れることは役に立ちません。ある意味で、これは演算子の優先順位の別の形式です。関数呼び出しは、他の何よりも緊密にバインドされます。

厳密に必要な数よりも多くの括弧を使用するのが本当に嫌いな場合は、単項演算子を使用して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

上記のステートメントは、実際には次のことを意味します (if $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 に答える