2009-07-14 9 views
6

私は、Perlでハッシュについて学ぶことを試みる単純なスクリプトを持っています。なぜ、Perlのeach()が2回目のハッシュ全体を繰り返し処理しないのですか?

#!/usr/bin/perl 

my %set = (
    -a => 'aaa', 
    -b => 'bbb', 
    -c => 'ccc', 
    -d => 'ddd', 
    -e => 'eee', 
    -f => 'fff', 
    -g => 'ggg' 
); 

print "Iterate up to ggg...\n"; 
while (my ($key, $val) = each %set) { 
    print "$key -> $val \n"; 
    last if ($val eq 'ggg'); 
} 
print "\n"; 

print "Iterate All...\n"; 
while (my ($key, $val) = each %set) { 
    print "$key -> $val \n"; 
} 
print "\n"; 

私は出力によって驚い: -

Iterate upto ggg... 
-a -> aaa 
-c -> ccc 
-g -> ggg 

Iterate All... 
-f -> fff 
-e -> eee 
-d -> ddd 
-b -> bbb 

私は最初の出力は、内部順序に応じて、「n」の要素となることができるように、キーがハッシュされていることを理解しています。しかし、なぜ後で配列をループすることができないのですか?どうしましたか ?

おかげで、

答えて

18

eachイテレーションを追跡するために、ハッシュに関連するポインタを使用しています。最初のwhileは2番目のwhileループとは異なり、それらの間に同じポインタが保持されていることはわかりません。

ほとんどの人が代わりにkeysを選ぶ、この(およびその他)の理由でeach避ける:

for my $key (sort keys %hash){ 
    say "$key => $hash{$key}"; 
} 

とにかく:

for my $key (keys %hash){ 
    say "$key => $hash{$key}"; 
} 

これは、あなたにも、繰り返し順序を制御できますループを早期に終了する場合は、eachを避けてください。

ところで、関数型プログラミングの支持者は、隠された状態の欠点を指摘するには、この機会を利用すべきです。ステートレスな操作(「テーブル内の各ペアのループ」)は、実際はかなりステートフルです。

+0

感謝を反復するために、あなたのコード内でキー%セットを使用することができます。ところで、「それぞれ」を最初に戻すことは可能ですか? –

+0

"%hash =%hash"が機能しているようです。 – jrockway

+6

(perlfaq4は、voidコンテキストでハッシュの "keys"を呼び出すことを提案しています。これは不必要なコピーを避けることができます)。 – jrockway

10

あなたはハッシュが完全に読み込まれると、ヌル配列は「(割り当てられたときには、偽(0) 値を生成する)リストコンテキストで返されており、各

perldoc -f each 

にはperldocを読むことができますスカラーコンテキストでは「undef」です。それ以降の "each"への次回の呼び出しは、再度反復を開始します。プログラム内のすべての "each"、 "keys"、 "values"関数呼び出しで共有される各ハッシュのためのイテレータはありません。 によってすべての要素をハッシュから読み取るか、または「キーハッシュ」または「ハッシュ値」を評価することによってリセットできます。

ので、あなたは(原因あなたの「最後」の文に)再び

print "Iterate upto ggg...\n"; 
while (my ($key, $val) = each %set) { 
    print "$key -> $val \n"; 
    last if ($val eq 'ggg'); 
} 
print "\n"; 
keys %set; 
print "Iterate All...\n"; 
while (my ($key, $val) = each %set) { 
    print "$key -> $val \n"; 
} 
print "\n"; 
関連する問題