8

「Beginning Perl」という本を読んでいるのですが、次の 2 つのステートメントが書かれています。

print "Test one: ", 6 > 3 && 3 > 4, "\n";
print "Test two: ", 6 > 3 and 3 > 4, "\n";

最初の行は改行なしで何も出力せず、2 行目は改行なしで 1 を出力します。

出力について混乱しています。著者によると、2 番目のステートメントは次のように言って奇妙な出力を示します。

print ("Test two: ", 6 > 3) and 3 > 4, "\n";

しかし、最初のステートメントが同じでないのはなぜですか? 印刷の優先順位と関係があると思いました。&& は print よりも優先順位が高いため、最初に評価されてから出力されます。「and」は print よりも優先順位が低いため、6 > 3 が出力されますが、print は 1 を返し、それが「and」で評価されます。しかし、これは本当に意味がありません。

リスト演算子の優先順位がどのように機能するかについて Perl のドキュメントを読みましたが、この例をまだ理解していません。2 つのステートメントを分析して、最初に出力されるものを教えてください。また、Perl のドキュメントで、リスト演算子が「左方向」および「右方向」であると言及されている場合の意味を説明できますか? ありがとう。


皆様、ご回答ありがとうございます。私は今それを理解しています。私は確かにcjmが言ったことをやっていて、左向きと右向きのリスト演算子があると思っていました。意味がわかったので、全体を理解しました。

4

3 に答える 3

12

まず始めに: list-operators は perl で優先順位が最も低いものの1 つですが、右側にのみあります。あなたはそれが何を意味するのかを尋ねます:まあ、それを簡単にしましょう. というリストトップがあるとしfooます。それが何をするかは問題ではありませんが、そこにあります。sub foo { map 10 * $_, @_ }各引数を 10 倍して返すようなものを簡単に作成できます。それは邪魔にならない:

print 1, 2, 3;と同等print( 1, 2, 3 );
print foo 1, 2, 3;です と同等です とprint( foo( 1, 2, 3 ) );
print 1, foo 2, 3;同等ですprint( 1, foo( 2, 3 ) );

foo右側で可能な限り飲み込んでいることがわかります— ステートメントの最後 (これまでのところ...) だけがそれを止めることができます。私たちが書いた場合、もちろん終わりの括弧が引き続き適用されるため、@array = (1, foo 2, 3);それは同等です。@array = (1, foo(2, 3) );

コンマも非常に優先度が低いので ("List operator (rightward)" のすぐ上)、listop への引数に必要なほとんどすべての種類の式を入れることもできます。ほとんどの場合、括弧を追加する必要はありません。数学、ビット演算子、比較、さらには正規表現の一致も優先されます。

優先順位が低いのは、スペルアウトされた論理接続詞andorxor、およびだけですnot。だから私たちが書くなら

foo 1, 2, 3 and 4;

つまり-の左側で停止する(foo(1, 2, 3) and 4)引数。これは不自然な例ではばかげているように見えるので、一般的な perl のイディオムに変えてみましょう:fooand

open $fh, '<', $filename or die "$! opening $filename";

これはと同等です

(open($fh, '<', $filename) or die("$! opening $filename"));

これは実際にはまったく同等です(そしてコンパイルされます)

die "$! opening $filename" unless open $fh, '<', $filename;

ステートメント修飾子形式のunless(これはまったく演算子ではなく、ステートメントごとに 1 回だけ許可され、ステートメントの最後にのみ使用されるため、実際には優先順位にはまったく関与しませんが、考慮することができますそれは「最低よりも低い」優先順位の左側です)。

とにかく、元のコード サンプルに戻ると、引数はprintのすぐ左で終わりand、 の右は完全に別のコンマ式になります。これは、ほんの数個の定数であり、無効なコンテキストで評価されるandため、何もしません。3 > 4"\n"

于 2010-08-09T09:29:59.873 に答える
8

これらのステートメントが完全な括弧でどのように表示されるかを次に示します。

print("Test one: ", ((6 > 3) && (3 > 4)), "\n");
print("Test two: ", (6 > 3)) and ((3 > 4), "\n");

>の優先順位が最も高く、次に&&、次に,、次にprint、次にand.

6 > 3に評価され1ます。 3 > 4false と評価されます。これは、Perl では、数値コンテキストでは 0 ですが、文字列コンテキストでは空の文字列になる特別な値です (ここのように)。したがって((6 > 3) && (3 > 4))、空の文字列が生成されます。

したがって、最初のステートメントはprint: "Test one: "、空の文字列、および改行に 3 つの引数を渡します。各引数を順番に出力します。

print2 番目のステートメントは、 :"Test two: "とに 2 つの引数のみを渡し1ます。に渡されなかったため、改行は印刷されませんprint

docsよりも「左方向」と「右方向」を説明する方法がわかりません。しかし、おそらくあなたを混乱させているのは、「左方向のリスト操作」と「右方向のリスト操作」があると考えていることです。それはそれが意味するものではありません。リスト演算子の右側のすべてがその演算子の引数として解釈されると言おうとしています( のような非常に優先順位の低いブール演算子のいずれかにヒットしない限りand)。しかし、リスト演算子の左側にあるものは、そのリスト演算子に関連付けられていません。

于 2010-08-09T07:36:41.807 に答える
4

「これは意味がない」という部分を除けば、おっしゃる通りです。

最初は

print "Test one: ", (6 > 3 && 3 > 4), "\n";

そして2番目

(print "Test two: ", 6 > 3) and (3 > 4, "\n");

use warnings警告 ( ) をオンにすると、警告が表示されます。これは、要素falseと改行を含むリストUseless use of a constant in void contextに評価される右側が使用されていないためです。and

edit : 3>4 is undefの主張を修正しました。False は undef ではありません。それは定義されており、何も出力しません。

于 2010-08-09T07:39:22.310 に答える