第50回 forとwhileの違い その2

第46回 forとwhileの違い その1 - bingo_nakanishiの他言語出身者のためのPerl入門
で、

あるときの例外を除いて、whileはforのように$_に値をいれません。

と述べました。その例外を紹介しましょう。それは、行入力演算子といっしょに使ったときです。

whileと行入力演算子

whileの( )の部分に行入力演算子を与えた場合は、$_にファイルの中身が読み取られます。

use strict;

open my $file, '<', 'hoge.txt';

while(<$file>){
 print $_;
}

結果:

aaaaaaaa
bbbbbbbb
cccccccc
dddddddd
eeeeeeee

whileの( )の部分がスカラーコンテキストであることを思い出すと、
whileが1回まわるごとに、$_に1行ずつ読み込まれていくのが納得できます。

forと行入力演算子

whileの( )の部分に行入力演算子を与えたように、
forの( )の部分にも行入力演算子を与えれます。

use strict;

open my $file, '<', 'hoge.txt';

for(<$file>){
 print $_;
}

結果:

aaaaaaaa
bbbbbbbb
cccccccc
dddddddd
eeeeeeee

結果はwhileのときと同じになりましたが、「whileと行入力演算子」を使った場合と、「forと行入力演算子」を使った場合には大きな違いがあります。


whileはスカラーコンテキストですから、1行ずつファイルの内容が読み込まれ、whileの中身がファイルが1行ずつ読み込まれるたびに処理されます。

それに対し、forはリストコンテキストですから、まず、ファイルの中身を全部、メインメモリに読み込もうとします。前回、配列に行入力演算子でファイルの中身を持たしたのと同じ理屈です。

forの中が回る前に全部ファイルの中身を読み込んでから、その読み込んだものに対してforがまわるのです。

ですから、大きなファイルを処理するときにforを使うとメインメモリを馬鹿食いしてしまいます。


参考:2008-10-12

まとめ

このように、whileとforはうまく使うタイミングを考え、使いこなしていく必要があるのです。