2010年9月9日木曜日

Perl best practices[Perlベストプラクティス] 10章 IO 10.1~10.10


このエントリーをはてなブックマークに追加


ファイルハンドルに裸のワードを使用しない



open FILE '<', $filename
or qroak "Can't open '$filename': $OS_ERROR";



 このFILEはシンボルテーブルのエントリ(グロブ)に格納される。


間接的はファイルハンドルを使用する


 レキシカル変数にファイルハンドルへの参照を代入することにより、名前の競合が防げるほか、スコープを外れたら自動的にファイルハンドルを自動的に閉じるというメリットもある。


ファイルハンドルはすぐにローカル化する。


 理由はいわずもがな。注意点としてはローカル化したあとにネストされたサブルーチンがあると、ローカル化された変数が継続して有効だと言う点。


IO::Fileモジュールを使用するか、引数3つのopenを使用する


 まれだが、'>temp.log<'などというファイル名が指定されると、入出力モードにバグが入り易い



open my $active, '<', $ACTIVE_LOG or croak "Can't open $ACTIVE_LOG: $OS_ERROR";

my $active = IO::File->new($ACTIVE_LOG, '<')
or croak "Can't open $ACTIVE_LOG: $OS_ERROR";



結果をチェックせずにファイルへのopen,close,printを行わないこと


 必ず毎回チェックを行うこと。
 しかし、毎回毎行チェックすると構文が汚れるので、13.2節を参考にFatalモジュールを使う。そうすると、組み込み関数で失敗すると例外が送出されるので、openする度に結果をチェックするコードを書かなくてよくなる。


for(<>)ではなくwhile(<>)を使用する


 forの反復リストはリストコンテキストなので、<>演算子がリストコンテキストで呼び出される。すると、可能な限りすべての行を読み取ってから、一時的なリストを作成する。これはすべての行を読み込み終わるまで、forループが開始しないことを表す。
 そのため、対話モードで使用することはできないし、メモリも入力に対して200%ほど必要になり、メモリ割り当てやスワッピングで処理速度が話にならないほど低下する恐れもある。
 入力を読み取る際はwhileを使用すること。ただし範囲(2..1000)はfor文を使用しても問題ない。


ファイルの丸呑みではなく行ベースのIOを使用する


 ファイル内容を丸呑みすると、1行ずつ処理する場合に比べて、時間がかかるし、堅牢性とスケーラビリティに欠ける。丸呑みすることの利点は、ファイルの内容が不安定な場合や、処理が複数行に渡る場合など。



while (my $line = <>) {
$line =~ s/$EXPLETIVE/[DELETED]/gxms;
print $line;
}



丸呑み



my $code = do { local $/; <$in> };


 $/は入力のセパレータ文字を指定するが、local化は初期値にundefが入るため、セパレータがundef、つまり存在しないので、行で区切られずに、ファイル内容を丸呑みする。
 また、$/の変更の影響を最小限に抑えるためにdoブロックで囲んでおく。

perl6では次のように自然に書くこともできる



use Perl6::Slurp;

my $text = slurp $file_handle;


これはスカラーコンテキストではファイル全体を読み込み、リストコンテキストでは1行ずつのリストとしてファイル全体を読み込む。
また、セパレータに段落や、正規表現を組み込むことも可能になる。





0 件のコメント:

コメントを投稿