• ベストアンサー

配列要素の$と@の違い

@a = (1,2,3); for($i = 0; $i <= $#a; $i++){ print $a[$i]; print @a[$i]; } 配列の要素は $a[$i] と書くのが正しいと思うのですが、ここの質問などで @a[$i] と書いているを何度か見かけました。試しに上記のソースで試してみたのですが、 @a[$i] でもエラーにならないし、$a[$i] と同じ結果が得られます。 そこで質問なんですが、 1 $a[$i] と @a[$i] で、何か違いは有るのでしょうか? 2 $a[$i] と書くべきなのか、どっちでも良いのか?

質問者が選んだベストアンサー

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

処理速度以外にも大きな違いがありますよ。 use strict; use warnings; my $tmpname = ($ENV{TMP} . 'sample'. $$); #my $tmpname = 'mogera.txt'; my $fh; open $fh, '>', $tmpname or die "can't create tmp file"; foreach (qw(foo bar baz hoge moge)) { print $fh $_, "\n"; } close $fh; my @ary1; my $tmp1; open $fh, '<', $tmpname; $ary1[0] = <$fh>; $tmp1 = <$fh>; seek $fh, 0, 0; my @ary2; my $tmp2; @ary2[0] = <$fh>; $tmp2 = <$fh>; close $fh; print $ary1[0]; print $tmp1; print $ary2[0]; print $tmp2; 実行結果をよく見てください。 前者は $tmp1 にも値が入りますが、$tmp2には入りません。 なぜかというと、Perlにはコンテキストというものがあって、 $ary1[0] はスカラーコンテキスト、@ary2[0] はリストコンテキストになります。 そしてリストコンテキストにおいて <$fh> のようにファイルから読み込むと、 ファイルの内容を全部読んでしまいます。 @ary2[0] = <$fh> の場合は、内容を全部読んだ上で最初のひとつだけ代入して 後は捨ててしまいます。 結論としては、それを意図していない限りは $ary[1] のように書きましょうということになります。 ということなので、use warnings しているとこれに関して警告が出されます。この件に関してはFAQにも載っていますので見てみてください。

参考URL:
http://www.kt.rim.or.jp/~kbk/perl-5.8/perlfaq4.html#what_is_the_difference_between__array_1__and__array_1_
venzou
質問者

お礼

詳しい回答ありがとうございます。 代入する時に $a[$i] と @a[$i] で違いが現れるケースがあるんですね。こういう「違い」が有るのか無いのか気になっていたのです。 $a[$i] を @a[$i] と間違えて使っていると、いつか大きな落とし穴にハマる可能性がありますね。 質問1の答え 代入した場合に違いが現れるケースがある 質問2の答え $a[$i] と書くべである(意図的にスライスを使う場合以外) という結論に至りました(私の中で)。すっきりしました。 YAMAMAYAさん、sakusaker7さん、ありがとうございました。

その他の回答 (1)

noname#43437
noname#43437
回答No.1

@を使って配列の要素を参照するのは、過去に流行った、よくある間違いです。 @a[$i] というような書き方は、正確には配列のスライスといい、 配列の一部をリストとして取り出す方法です。 たとえば、 @a[1,3] は、配列aの1番目と3番目の要素リストとなり、 @a[3]は、配列aの3番目の要素のリストとなります。 このリストを、スカラー(配列ではない一つだけの値)として評価すると、リスト中の最後の値が採用されます。 なので、@a[3]は、配列の3番目の要素を返す、ということになり・・・使い方の間違いに気づかずにそのまま使えてしまう、ということになったのです。

venzou
質問者

お礼

早速の回答ありうございます。 「配列のスライス」と言うのは知りませんでした。勉強になりました。 @a[$i] でもプロセスは異なりますが最終的に、$a[$i] と同じ結果が得られると言う事ですね。(試してみましたが、処理速度は $a[$i] の方が速かったです) 処理速度以外に違いが無いなら、間違う人は後を絶たないでしょうね。「間違ってますよ」って注意もしにくいし。困ったもんですね。(^^;

関連するQ&A