スキップしてメイン コンテンツに移動

投稿

2月, 2019の投稿を表示しています

SelectSaver の話

筆者の好きな Perl 5 標準モジュールの話をする。実用性は特にない。SelectSaver というモジュールを知っているだろうか。 なにしろラクダ本にも載っている天下の標準モジュールである。ちょっとでも Perl 5 をかじったことのあるプログラマなら知っているだろう。1それでこれは何かというと、オブジェクト生成時にファイルハンドルを select し、破棄時に元のファイルハンドルを再び select するガードオブジェクト、要するに select 専用 Scope::Guard である。このモジュールの意義を知るためにはまず select を知る必要がある。 ニワカでなければ誰でも知っていることだが2、Perl 5 の select は無ないし一引数版 (以下 Prolog 風に select/1 と書く) と三ないし四引数版 (同 select/4) でセマンティクスが丸っきり違う。実質オーバーロードされていると言って良い。 select/4 は単にシステムコール select(2) の Perl 版だが、select/1 は print / say / write / $| (AUTOFLUSH) などが使うデフォルトのファイルハンドルを選択するという全く無関係な機能を提供する。 標準出力をリダイレクトするわけではない。STDOUT はそのままで print みたいな標準関数や $| みたいな特殊変数が指定されたファイルハンドルを使うようになるだけである。また戻り値は直前に select されていたファイルハンドルを返す。ちなみに引数なしで呼び出すと現在の設定を変更せずに同じ値を返す。プロセスのグローバルな状態を書き換えるなんとも C っぽい関数だが、例えば一つのファイルにひたすら書き出すときにファイルハンドルを省略できて便利である:sub print_batch { my ($fh) = @_; my$old_fh = select$fh; print ...; print ... if ...; print ... for1 .. 10; failable_instruction(...); # XXX: 失敗し得る関数呼出し ... select$old_fh; } しかし上記の関数には問題がある。例外安全で…