2006 年 3 月 17 日 23 時 58 分

モジュールのフォールバック


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


昨日は、Encode モジュールがあることが前提だった。

そのため、Encpde がない環境で走らせると、
Can't locate Encode.pm in @INC
というエラーになってしまう。

だからといって、最も簡単に導入できる、
jcode.pl を使うと、Unicode の対応ができない。
Encode がある環境では Encode を使いたい、
ない場合は Jcode、それもなければ jcode.pl が理想だ。
つまり、「フォールバック」を行いたい。

通常、モジュールを使う場合、「use モジュール」とするが、
そのままだと、上述の通りよろしくない。
さて、それを実現するためにはどうすれば良いか。

Perl には eval という便利な関数がある。
特徴として、実行時のエラーを補足する機能と、
文字列に格納されたコードを実行時にコンパイルし、
その場で実行する機能がある。

これを使って、Encode モジュールを読み込んでみる。

eval 'use Encode;';

本来、use は、コンパイル時に実行されるが、
文字列として渡してやることで、
コードが eval に達したタイミングで実行が可能となる。

文字列を渡した場合、実行時に文字列を直ちにコンパイルし、
コードとしてこの場に存在したかのように実行される。
そのため、成功した場合は、use Encode が実行され、
Encode モジュールが使用可能となる。

もし失敗した場合はどうなるか。
eval でエラーが発生した場合、
$@ にエラーメッセージが格納される。

eval 'コードとか';
if ($@) {
    # 失敗時の処理。
} else {
    # 成功時の処理。
}

今回の場合、eval 後に $@ を調べれば、
フォールバックが必要かどうか分かる。
では、読み込みのコードを書いてみよう。

BEGIN {
    eval 'use Encode;';
    return unless $@;

    eval 'use Jcode;';
    return unless $@;

    eval "require 'jcode.pl';";
    return unless $@;

    die "お手上げ~";
}

こうすれば、モジュールが環境にない場合でも、
最善のモジュールを読み込むことができるようになる。

BEGIN ブロックは、コンパイル時、
最も早い段階で実行される。
本来、モジュールは、use で取り込むので、
このタイミングでの実行が重要になるのだ。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.