Perlにおけるモジュールとパッケージの関係
Perlで分かりづらい概念の一つに「モジュール」と「パッケージ」の関係が挙げられます。ようやく最近理解できてきた様な気がするので、以下にそのメモを。
例として、以下の様なスクリプト本体とモジュールが有ったとします。
/usr/local/bin/script.pl
#!/usr/local/bin/perl
use strict;
use warnings;
require Some::Module;
my $value = Some::Module::func();
print "$value\n";
/usr/local/lib/perl5/site_perl/5.10.1/Some/Module.pm
package Some::Module;
use strict;
use warnings;
sub func {
return localtime;
}
1;
script.plの中で「require Some::Module;」と記述する事で、「/usr/local/lib/perl5/site_perl/5.10.1/Some/Module.pm」というモジュールが"実行"されます。このモジュールの中には、"func"というサブルーチンの定義だけが書かれているので、この段階では特にサブルーチンの中のコードが"実行"される事は有りません。定義されるだけです。
「/usr/local/lib/perl5/site_perl/5.10.1/Some/Module.pm」の中には「package Some::Module;」という記述が有る事で、「Some::Module」というパッケージ名が定義されます(名前空間と考えると分かりやすいですね)。このパッケージ名が定義された事で、「script.pl」の中からSome::Moduleの中に有るfuncという関数が呼び出す事が出来る様になるのです。
そう、重要なのはrequireにより呼び出された時に、モジュールは"実行される"という事です。モジュールの中のコードが実行される事でパッケージ名が"初めて"定義されるのです。つまり、requireするまではSome::Moduleというパッケージ名は存在しないのです。
パッケージ名が定義されていないのに、なぜ「require Some::Module;」と書けるのか?ここが最も理解しづらいポイントでした。
実は、ここで記述している"Some::Module"はパッケージ名を記述しているのではなく、単にモジュールファイルのパス名を記述しているだけなのです。だから、「require Some::Module;」と書けるのです。
Perlではrequireで指定されている「Some::Module」をライブラリの検索対象のパス配下に有る(この例では「/usr/local/lib/perl5/site_perl/5.10.1/」)、「Some/Module.pm」というファイルを探して実行しろ、と解釈しているのです。
Perlでは、モジュールを配置するパス名+ファイル名と、パッケージ名を一致させる習慣になっています。そうしないと、そのパッケージ名がどのモジュールで定義された物なのか分かりづらいですからね。
逆に言うと、requireとpakageのそれぞれにまったく同じ文字列(この例ではSome::Module)が書かれているのに、それらは全然違う事を意図しているので、凄く混乱し易いのです(requireの後ろはパス名、packageの後ろはパッケージ名)。図に整理するとこんな感じになります。
パッケージの階層と呼び出す時のPATHがきちんと整合している事を確認しましょう。
修正2010/2/26
誤り例が誤りという情けない指摘をいただきました。ひとまずさっくり書き直したのですが、Perl To The Peopleへ移す時にもう少しちゃんと考え直します。

コメント[2]
最後の箇所で、パッケージの指定方法
package Module;
には問題はないはずです。
>一番よくやる間違いは、パッケージ名にモジュールのファイル名を記述してしまう事です。
これは、名前空間をパッケージ名にしているので
その場合、呼出側のPATH指定に問題がある。。の間違いじゃないでしょうか。逆に混乱をまねいてしまいます^^;
Posted by 通りすがり at 2010年2月26日 16:39 | 返信
ご指摘ありがとうございます。確かにPATH名が間違っている、パターンですね。修正します。
Posted by ash
at 2010年2月26日 22:15 | 返信
コメントする