*STDINが本当に必要な時以外は<*ARGV>を使用する。
*STDINは、現在標準入出力に用いているものを常に指すわけではないし、ファイル名を指定しなければ(open *STDIN '<' $filename or croak...)、コマンドラインで指定されたファイルから・・・という意味にはならない。
*STDINは常に0番目のファイルディスクリプタを指す。デフォルトがターミナルであればいいが、パイプやファイルの中身を読んで、内容から他のデータを読み込みにいく等はできない。(そのファイル自体を指す)
普段使用している*ARGVを用いるほうがいい。(*ARGVは<>で表せる)
while (my $line = <>) {
print substr($line, 2);
}
print文では常にファイルハンドルを中括弧で囲む
レキシカルファイルハンドルを中括弧で囲むと、目につき易くなる。
以下のコードが、コンマを忘れただけだと思われないようになる。
print {$file} $name, $rank, "\n";
IO::Handleモジュールを使用してprintサブルーチンを使用する手もある。
対話形式の入力を得る場合には常にプロンプトを表示する
これを実装するのはかなり難しいので、以下のCPANモジュールを使用する。
use IO::Interactive qw( is_interactive );
if (is_interactive()) {
print $PROMPT;
}
プロンプトの表示にはIO::Promptを使用する
対話形式で入力を取得したい場合、IO::Promptを使用すると簡単。
これは質問、回答、検証という一連の処理を抽象化できる。
#通常はコレ
my $cmd = $EMPTY_STR;
CMD:
while ($cmd !~ $QUIT) {
if (is_interactive()) {
print get_prompt_str();
}
$cmd = <>;
last CMD if not defined $cmd;
chomp $cmd;
execute($cmd)
or carp "Unkown command: $cmd";
}
#IO::Promptを使用した場合
while ( my $cmd = prompt(get_prompt_str(), -fail_if => $QUIT) ) {
execute($cmd) or carp "Unkown command: $cmd";
}
$cmd変数のスコープがループ内になり、改行も自動的にchompされる。
対話モード以外の処理がしばらく続く場合は、進行状況をユーザに伝える
これには、Smart::Commentsを使用する。
use Smart::Comments;
for my $possible_confg ( @CONFIG_PATH ) { ### 初期化...終了
init_from($possible_config);
}
my $connection;
TRY:
for my $try (1..$MAX_TRIES) { ### サーバへの接続...終了
$connection = connect_to($REMOTE_SERVER, {timeout=>$TIMEOUT});
last TRY if $connection;
}
croak "Can't contact server ($REMOTE_SERVER)"
if not $connection;
#ここから対話モード開始
このモジュールはwhile,forと同じ行に、###マークが付いたコメントを配置することで、自動プログレスインジケータ(処理中であることを表す表示)を生成することができる。
詳細は18.13節「半自動デバック」参照。
自動フラッシュを設定する場合は、生のselectを使用しない
フラッシュは、バッファにたまったデータを吐き出すこと。
よく使われる下記のコードは保守しにくい。
select ((select($fh), $|=1)[0]);
selectはファイルハンドルをprint文のデフォルトの出力先として使用する。グローバルで。
レキシカルファイルハンドルを使用する場合には、IO::Handleを使用することで簡単に書ける。
use IO::Handle;
$fh->autoflush();
*STDOUT->autoflush();#パッケージスコープの標準ファイルハンドルでも使用可能
0 件のコメント:
コメントを投稿