2016-04-25 12 views
4

私は "Programming Perl"と読んでいて、理にかなっていないような奇妙な例が​​ありました。 Perlのコンマ演算子がスカラーコンテキストで使用されたときの最終結果のみを返す方法について説明しています。Perl "逆コンパートメント演算子"(Programming Perl、第4版の例)

例:本はその後、私にしかし数ページ後に(82ページ)

# A "reverse comma operator". 
return (pop(@foo), pop(@foo))[0]; 

"コンマ演算子を逆に" これはないのこの例を示します

# After this statement, $stuff = "three" 
$stuff = ("one", "two", "three"); 

全く逆に見える..?

例:これは、通常のカンマ演算子のいずれかの方法を逆にどのように

# After this statement, $stuff = "three" 
$stuff = reverse_comma("one", "two", "three"); 

# Implementation of the "reverse comma operator" 
sub reverse_comma { 
    return (pop(@_), pop(@_))[0]; 
} 

?結果は同じで、逆もありません!

正確なページにはlinkがあります。この例は一番下にあります。

+0

を役に立てば幸い

を何ができるかの一例である[ - 1] 'などのようなものです。 [あなたはこれで最初に混乱しているわけではありません。](http://computer-programming-forum.com/53-perl/0aa44266bcb822b5.htm) – ThisSuitIsBlackNot

+1

ここでの議論はスライスに関するものなので、 '(foo、bar)[0]'を「逆カンマ演算子」として返します。リストをアセンブルする際の 'pop()'の選択は、せいぜい不幸です。 – tjd

+0

@ThisSuitIsBlackNot:添え字が-1の場合、右手側を保持する非リバースカンマ演算子と同じ結果になります。下付き文字0では、左辺を保持します。 –

答えて

8

これは悪い例であり、忘れてはいけません。

何それは実証のは簡単です:

  • 通常は、最後に評価さコンマ演算子のインスタンスを解釈することができ、スカラコンテキストでは、カンマで区切られた式のシーケンスを、持っている場合順序で。

  • ただし、そのシーケンスをかっこで囲んで末尾に[0]と貼り付けると、そのシーケンスがリストに変わり、その最初の要素が取り込まれます。

    my $x = (1, 2, 3)[0]; 
    

    何らかの理由で、本書ではこれを「逆コンマ演算子」と呼びます。これは誤った名前です。それは最初の要素が取られている単なるリストです。

本は混乱事項さらに引数に二回pop機能を使用することです。これらは左から右に評価されるので、最初のpop"three"に、次の1つは"two"に評価されます。

いずれの場合でも、実際のコードでコンマまたは「逆コンマ」演算子を使用しないでください。どちらも将来の読者に混乱を招く可能性があります。

5

これはかわいい、巧妙な例ですが、それについてはあまりにも難しいと思って、その目的から気をそらす。この本のこのセクションでは、リストスライスを見せています。リストにあるものに関係なく、リストをスライスする以外のものは、サンプルの目的と密接に関連していません。


あなたは(私たちは結合法の限界であったため、我々は文字通りのいずれかのより多くのページに合うことができませんでした)非常に大きな本の82ページだけですので、我々はで投げる可能性があまりありません君は。他のリストスライスの例の中に、私が実際のコードで使っていないこの巧妙なものがあります。それは、しかし、人為的な例の呪いです。

しかし、逆コンマ演算子があったとします。カンマの両側を評価する必要があります。多くの答えは「最初のものを返す」のために正しく機能します。しかし、それは機能ではありません。あなたがそれらの1つを持っていても、すべての式を訪問する必要があります。

私はすぐに間接参照、そのそれぞれが、その後何かを出力無名サブルーチンのシリーズで、このはるかに高度なバージョンが結果を返す考えてみましょう:

use v5.10; 

my $scalar = (
    sub { say "First"; 35 } ->(), 
    sub { say "wantarray is ", 0+wantarray } ->(), 
    sub { say "Second"; 27 } ->(), 
    sub { say "Third"; 137 } ->() 
    ); 

括弧が代入演算子の結合するので唯一の優先順位のためにそこにありますコンマ演算子よりも緊密に。そこにはリストはありませんが、1つのように見えます。

出力は、Perlはそれが最後の1に保たれていても、それぞれの評価を行っていることを示しています

First 
wantarray is 0 
Second 
Third 
Scalar is [137] 

乏しいという名前wantarray内蔵のリターンを偽、サブルーチンはそれがスカラーコンテキストであると考えていることを指摘しました。

ここでは、すべての式を評価しながら最初のものを保持するように、それを反転させたいとします。あなたはリテラルリストへのアクセスに使用することができます:サブスクリプションの追加により

my $scalar = (
    sub { say "First"; 35 } ->(), 
    sub { say "wantarray is ", 0+wantarray } ->(), 
    sub { say "Second"; 27 } ->(), 
    sub { say "Third"; 137 } ->() 
    )[0]; 

を、右側は現在のリストであり、私は最初の項目を引き出します。 2番目のサブルーチンはそれがリストコンテキストにあると考えていることに注目してください。

First 
wantarray is 1 
Second 
Third 
Scalar is [35] 

しかし、これをサブルーチンに入れてみましょう。

my $scalar = reverse_comma(
    sub { say "First"; 35 }, 
    sub { say "wantarray is ", 0+wantarray }, 
    sub { say "Second"; 27 }, 
    sub { say "Third"; 137 } 
    ); 

say "Scalar is [$scalar]"; 

sub reverse_comma { (map { $_->() } @_)[0] } 

それとも、私は他のものの結果を使用します。私はまだ、私は他のものの結果を使用することはありませんにもかかわらず、各サブルーチンを呼び出す必要がありますか?私が少し違ったことをしたならどうしますか?

use v5.10; 

my $last; 

my $scalar = reverse_comma(
    sub { say "First"; 35 }, 
    sub { say "wantarray is ", 0+wantarray }, 
    sub { say "Second"; 27 }, 
    sub { say "Third"; 137 } 
    ); 

say "Scalar is [$scalar]"; 
say "Last is [$last]"; 

sub reverse_comma { (map { $last = $_->() } @_)[0] } 

今私はスカラーカンマを面白くする機能を参照してください。私が評価された式に$last設定の副作用を追加します。これは、すべての式を評価し、そのうちのいくつかは、副作用があるかもしれません:

First 
wantarray is 0 
Second 
Third 
Scalar is [35] 
Last is [137] 

それはtchristは、シェルスクリプトと便利であること巨大な秘密ではありません。 Perlからcshへのコンバータは、基本的に彼の受信箱(またはcomp.lang.perl)でした。彼の例ではイディオムのようないくつかのシェルが現れます。 1つのステートメントで2つの数値を入れ替えるというトリックのようなもの:

use v5.10; 

my $x = 17; 
my $y = 137; 

say "x => $x, y => $y"; 

$x = (
    $x = $x + $y, 
    $y = $x - $y, 
    $x - $y, 
    ); 

say "x => $x, y => $y"; 

ここで副作用が重要です。

だから、戻ってラクダに、私たちは、副作用を持っている事がpop配列演算子であるところの例があります。

use v5.10; 

my @foo = qw(g h j k); 

say "list: @foo"; 

my $scalar = sub { return (pop(@foo), pop(@foo))[0] }->(); 

say "list: @foo"; 

これは、すべてのカンマのいずれかの側に、各表現を披露します評価される。私たちは完全な例を示さなかったので、サブルーチンラッパーで投げた:

list: g h j k 
list: g h 

しかし、これのどれもが、リテラルリストにインデックスを付けるたそのセクションのポイントはなかったです。この例のポイントは、他の例やPerlの機能とは異なる結果を返さないことでした。カンマ演算子の動作が異なると仮定して同じことを返すことでした。セクションはリストスライスに関するものであり、リストスライスを表示しているので、リスト内のものは重要ではありませんでした。

+0

うわー、それは毎日あなたが作者に直接話すことはありません! :)正確に「逆コンマ演算子」はどうでしょうか?この例のコードはどのようにしてreturn(pop(@foo)、pop(@foo))[0];が期待どおりに動作するはずですか? – tjwrona1992

+0

第4版の私のコピーを開き、15行目と16行目の例を参照してください。 – tjd

+0

スライスは左側を保持しますが、左側の 'pop'が最初に評価されたので、' @ _ 'の最後の要素を返します。 – ThisSuitIsBlackNot

2

例をもっと似てみましょう。

コンマ演算子:

$scalar = ("one", "two", "three"); 
# $scalar now contains "three" 

逆コンマ演算子:

$scalar = ("one", "two", "three")[0]; 
# $scalar now contains "one" 

$scalarは、通常のカンマ演算子が与える最初の式の結果を取得しますので、それは「逆コンマ」です最後の表現。 (あなたがLispのについて何を知っている場合、それはprognprog1の違いのようなものだ。)

「逆コンマ演算子」の実装サブルーチンは、このようなものになりますよう:

sub reverse_comma { 
    return shift @_; 
} 
+0

これは、カンマ演算子がすべての式を評価するという重要な点を欠場します。それを維持するには、すべての引数を調べて、最初の引数を返す必要があります。しかし、それは例のポイントにも近くない。それは単なるリストスライスの例でした。 @briandfoy、ねえ、 –

+2

? Perl 5には遅延評価がありません。式は '@ _ 'に置かれたときに評価されます。サブは何もする必要はありません。 – cjm

+0

あなたの例は、単純なスカラー値を使うことで、スカラーのカンマの例の点を関数であいまいにすると思います。 –

0

通常カンマを$b

の値に

my $v = $a, $b 

セット$vをそのオペランドを評価して、右側のオペランドの値を返します。リストのスライスを実証する目的のために

、キャメルはコンマ演算子のように動作しますが、代わりにそのオペランドを評価するいくつかのコードを提案し、そのような

何かをすることができ左側オペランドの値を返しています本当にこれだけです$a

の値に$vを設定し、この

my $v = ($a, $b)[0] 

のように、リストのスライスで行わ。本書では、リバースカンマサブルーチンが必要であることを示唆していないので、2つの式を順番に評価して最初のものを返すという問題を単に考慮しています。評価の順序は、2つの式は本の中の例では、架空の問題は、この

ある

値を返すだけでなく、配列を変更popを使用する理由である、副作用を持っているときにのみ関連します

は、私は通常それがこの

などの一時的な変数を、必要となるサブルーチンは配列の最後の2つの要素を削除してから、最後の要素

にするために使用するものの値を返すようにしたいと仮定しますリストスライスの一例として、

my $last = pop @foo; 
pop @foo; 
return $last; 

しかしコード、これはまた

# A "reverse comma operator". 
return (pop(@foo), pop(@foo))[0]; 

を働くだろうことを示唆している。この勧告ではありませんので、ご了承ください。これを行うにはいくつかの方法があります。もう一つの文の方法は

return scalar splice @foo, -2; 

であるが、それは本のそのセクションのトピックであるリストのスライスを、使用していません。実際には、本の著者が一時変数を使った単純な解以外の提案をするかどうかは疑問です。これは純粋に、リストのスライスが、私はそれは私がそれはタイプミスだと思うだろうと `(ポップ(@_)、ポップ(@_))である必要があり

関連する問題