14

Perlがへの引数の解析を処理する方法に頭を悩ませようとしていますprint

なぜこれなのか

print $fh $stufftowrite

期待どおりにファイルハンドルに書き込みますが、

print($fh, $stufftowrite)

代わりにファイルハンドルを書き込みますか?STDOUT

私の推測では、それは次のドキュメントの警告と関係があると思いますprint

対応する右括弧でprintの引数を終了させたくない場合を除いて、printキーワードの後に​​左括弧を付けないように注意してください。すべての引数を括弧で囲みます(または+を挿入しますが、見栄えはよくありません)。

最初の形式(関数の引数を括弧で囲む言語から来ているので、私には正しくないようです)に慣れるべきですか、それともPerlに私が望むことをするように指示する方法はありますか?

これまでのところ、1番目、2番目、および両方のパラメーターを括弧で囲んで多くの組み合わせを試しましたが、成功しませんでした。

4

4 に答える 4

18

リストに

この構造は、 「bareword (LIST1), LIST2関数barewordを引数に適用する」ことを意味しますが、「結合リストの引数に適用する」ことを必ずしも意味するわけではありません。これは、引数をグループ化するために重要です。LIST1bareword +(LIST1), LIST2barewordLIST1, LIST2

my ($a, $b, $c) = (0..2);
print ($a or $b), $c;  # print $b
print +($a or $b), $c; # print $b, $c

プレフィックス+を使用して、ハッシュ参照をブロックから、関数をベアワードから区別することもできます。たとえば、ハッシュを添え字化する場合:$hash{shift}shift要素を返し$hash{+shift}、関数を呼び出してshift値のハッシュ要素を返しますshift

間接構文

オブジェクト指向のPerlでは、通常、矢印構文を使用してオブジェクトのメソッドを呼び出します。

$object->method(LIST);   # call `method` on `$object` with args `LIST`.

ただし、動詞を最初に置く間接表記を使用することは可能ですが、お勧めしません。

method $object (LIST);   # the same, but stupid.

クラスは(構文上の意味で)それ自体の単なるインスタンスであるため、クラスのメソッドを呼び出すこともできます。これが理由です

new Class (ARGS);  # bad style, but pretty

と同じです

Class->new(ARGS);  # good style, but ugly

ただし、これによりパーサーが混乱する場合があるため、間接的なスタイルはお勧めしません。

しかし、それは印刷が何をするかについてのヒントを与えます:

print $fh ARGS

と同じです

$fh->print(ARGS)

実際、ファイルハンドル$fhはクラスのオブジェクトとして扱われますIO::Handle

(これは有効な構文の説明ですが、完全には真実ではありません。ソースIO::Handle自体は行を使用しprint $this @_;ます。print関数はこのように定義されています。)

于 2012-12-01T12:25:00.753 に答える
15

タイプミスがあるようです。2番目のprintステートメントのファイルハンドルと引数の間にコンマを入れました。これを行うと、ファイルハンドルが引数として表示されます。これは、字句ファイルハンドルにのみ適用されるようです。グローバルファイルハンドルを使用すると、致命的なエラーが発生します

No comma allowed after filehandle at ...

したがって、明確にするために、絶対に括弧が必要な場合は、次のようにしますprint

print($fh $stufftowrite)

個人的には、必要がない限り括弧を使用しない方が好きです。括弧は混乱を招くだけだからです。

于 2012-12-01T11:54:38.563 に答える
9

現代のPerlの本は、第11章(「避けるべきこと」)のセクション「間接表記のスカラーの制限」で次のように述べています。

構文のもう1つの危険性は、パーサーがオブジェクトとして単一のスカラー式を予期することです。集計変数に格納されているファイルハンドルへの出力は明白に思えますが、そうではありません。

# DOES NOT WORK AS WRITTEN
say $config->{output} 'Fun diagnostic message!';

Perlは$configオブジェクトでsayを呼び出そうとします。 print、、、closeおよびsay(ファイルハンドルを操作するすべてのビルトイン)は、間接的に動作します。これは、ファイルハンドルがパッケージグローバルの場合は問題ありませんでしたが、字句ファイルハンドル(ファイルハンドル参照)を使用すると、間接目的語の構文の問題が明らかになります。これを解決するには、意図した呼び出し元を生成する部分式を明確にします。

say {$config->{output}} 'Fun diagnostic message!';

もちろんprint({$fh} $stufftowrite)可能です。

于 2012-12-01T12:27:16.277 に答える
3

これがの構文のprint定義方法です。とても簡単です。修正するものは何もありません。ファイルハンドルと残りの引数の間にコンマを入れると、式は。print LISTではなくとして解析されprint FILEHANDLE LISTます。はい、それは本当に奇妙に見えます。本当に変です。

そのまま解析されないようにする方法は、print LIST合法的に解析できる式を提供することprint FILEHANDLE LISTです。引数を括弧で囲んでprint、通常の関数呼び出しのように見せようとしている場合は、次のように言うことができます。

print($fh $stufftowrite); # note the lack of comma

あなたも言うことができます

(print $fh $stufftowrite);

あなたがやろうとしていることがprint、周囲のコードから式を引き離すことである場合。重要な点は、コンマを含めると解析が変わることです。

于 2012-12-05T05:22:40.707 に答える