一つ前のエントリでお世話になった時に目に入った、nlog(n)さんのパッチとしてのプラグインとその可能性にトラックバック。
このパッチはプラグインディレクトリ plugins にインストールするものだが,普通のプラグインとは動作が異なっている。「再構築が不要」というだけでも違うことが分かる。
自分もこのパッチを当てた時、同じようなことを思った。中を見ると、問題となっているメソッドの型グロブを書き換え、処理を無理矢理変えている。
例えば、以下のような2つのファイルからなるスクリプトがあったとする。
#Bug.pm ==========
package Bug;
sub new{ bless \"$_[1]", $_[0] }
sub hello{ print "bugbugbug!\n" }
1;#main.pl ==========
use Bug;
my $plugin_dir = "plugin";
opendir(DIR, $plugin_dir);
while(my $file = readdir(DIR)){
next if($file !~ /\.pl$/);
eval "require \"$plugin_dir/$file\";";
warn $@ if($@);
}
closedir(DIR);
my $bug = new Bug("Mike");
$bug->hello();
実行結果
bugbugbug!
見ての通り、Bug.pmのhello()メソッドにはバグがある。また、main.plはpluginと言うディレクトリにあるスクリプトを全てrequireするように出来ている。
この状態で、以下のパッチを作ると、動作が改善される。
#plugin/patch.pl ==========
*Bug::hello = sub {print "I am ${$_[0]}.\n"};実行結果
I am Mike.
なお、書き換え前の関数のリファレンス\&Bug::helloを保存しておけば、新しい&Bug::helloの中から古いルーチンを呼ぶことも出来る。
とても便利で、perlならではと言ったところかな。応用すれば、CPANのモジュールの動きが気に食わない時にも役に立ちそう。ただし、この方法を使えばどんなサブルーチンの動作も書き換えられてしまうので、悪用すると大変危険であり、注意が必要だ。