Perl::Critic / UNIVERSAL::require

このところ社内の技術勉強会で取り上げているテーマの Perl::Critic。このモジュールは、Damian ConwayPerl Best Pracitice に書かれているスタンダードな Perl のコーディングスタイルをチェックするためのものです。Perl::Critic をインストールすると perlcritic というコマンドがインストールされ、それを使うことで自分が書いた Perl のソースをチェックしたりできるという。

いろんなコーディングスタイルのルールとかは、Perl::Critic::Policy のサブクラスに記述されていて、pod で全部読めます。

この Perl::Critic なポリシーの中に Perl::Critic::Policy::BuiltinFunctions::ProhibitStringyEval というのがあります。これは eval には文字列じゃなくてブロックでコードを与えよ、というルール。

eval "print $foo";        #not ok
eval {print $foo};        #ok

理由は pod を参照していただくとして、eval を lazy な use や require のために使うときはどちらにしろ文字列で eval を使わないといけない。(コメントにありますが、モジュールファイル名で require したときのみなんとかなる) そこで、eval で use とか require するのが嫌! ってときには UNIVERSAL::require を使うという手があるかなと思いました。

これを使うと、

eval "require $module"

が、

$module->require;

と書け、OO厨*1にはたまらない感じ。

ただ、今 id:hideoki と話しててわかったのですが、UNIVERSAL::require も中では文字列で eval をしてるので、"The string form of eval is recompiled every time it is executed, whereas the block form is only compiled once. " という点においては一緒のようなんですけど。

ちなみに、UNIVERSAL::require は Catalyst で使われてるのをみて知りました。

*1:PofEAA読書会でみんなが連呼していた言葉。厨という言葉がついているが必ずしも揶揄というわけではないらしい。