Perlモジュールの基礎とインストール

 効率よくプログラムを作るためには,既にあるものを再利用することが大きなポイントになります。今回はPerlでの再利用の基本となるモジュールについて説明をします。

 Perlでは「モジュール」が,再利用の基本的な単位になります。モジュールは変数や関数を他のものと確実に区別するために独自の名前空間を定義し,その名前空間に対応する名前を持ったファイルです。プログラムにに取り付けられるパーツのようなものです。各パーツは中の部品がはみ出したり,他のパーツとぶつからないように名前空間というカバーがついています。

 モジュールのファイルの内容を名前空間に対応するディレクトリ名やファイル名で保存します。「My::Dir」という名前空間であれば「My」というディレクトリに「Dir.pm」というファイル名で保存します。拡張子「pm」は,Perlのモジュールを表しています。MyDirという名前空間であれば「MyDir.pm」,「My::Dir::Size」であれば「My/Dir/Size.pm」という名前といった具合です。

 実際にモジュールのファイルの中身を見てみましょう。例えば,ディレクトリ内のファイルの大きさを求める関数「getDirSize」をモジュール化すると図1のようになります。2行目の「package」によって,名前空間を「My::Dir」とすることを宣言しています。Perlスクリプトの終わりを示す「__END__」(21行目)の直前の「1;」はファイル全体を読み込む処理が正常に終わったことを示すためのおまじないです。「1」に限らず,True(真)に評価される値であれば何でも構いません。


 1: #!/usr/bin/perl
 2: package My::Dir;
 3: use strict;
 4: our $Dir;  #5.005などではuse vars qw($Dir);
 5: our $Sum;  #5.005などではuse vars qw($Sum);
 6: sub getDirSize($) {
 7:   my($sDir) = @_;
 8:   $sDir ||= '.';
 9:   my $iSum = 0;
10:   opendir IN, $sDir;
11:   while(my $sFile=readdir(IN)) {
12:     next if(($sFile eq '.') or ($sFile eq '..'));
13:     $iSum += (-s "$sDir/$sFile");
14:   }
15:   closedir IN;
16:   $Dir = $sDir;
17:   $Sum = $iSum;
18:   return $iSum;
19: }
20: 1;
21: __END__
22: =POD
23: =head1 名前
24:
25: My::Dir : ディレクトリ関連モジュール
26:
27: =head1 概要
28:
29: use strict;
30: use My::Dir;
31: print My::Dir::getSizeDir('mydir');
32: print $My::Dir::Dir, ' : ', $My::Dir::Sum, "バックスラッシュn";
33:
34: =head1 説明
35:
36: =head2 getSizeDir($)
37:
38: 指定されたディレクトリに入っている
ファイルの大きさの合計を計算する。 39: 40: =head2 $My::Dir::Dir 41: 42: 前回、指定されたディレクトリ名 43: 44: =head2 $My::Dir::Sum 45: 46: 前回、求めた大きさの合計 47: 48: =cut
図1●モジュール「My::DirSize」(Dir.pm)
ディレクトリに入っているファイルの大きさの合計を求める関数を定義しています。

 さらにモジュールは,Perlのクラスとして利用できます。先ほどのコードをオブジェクト指向の記述で書き換えると図2のようになります。こちらはMy/DirOO.pmというファイル名で保存します。


 1: #!/usr/bin/perl
 2: package My::DirOO;
 3: use strict;
 4: sub new($) {
 5: my ($sClass) = @_;
 6: bless {}, $sClass;
 7: }
 8: sub getDirSize($$) {
 9: my($oSelf, $sDir) = @_;
10: $sDir ||= '.';
11: my $iSum = 0;
12: opendir IN, $sDir;
13: while(my $sFile=readdir(IN)) {
14: next if(($sFile eq '.') or ($sFile eq '..'));
15: $iSum += (-s "$sDir/$sFile");
16: }
17: closedir IN;
18: $oSelf->{Dir} = $sDir;
19: $oSelf->{Sum} = $iSum;
20: return $iSum;
21: }
22: 1;
23: __END__
24: =POD
25: =head1 名前
26:
27: My::DirOO : ディレクトリ関連モジュール(OO)
28:
29: =head1 概要
30:
31: use strict;
32: use My::DirOO;
33: my $oDir = My::DirOO->new;
34: print $oDir->getSizeDir('mydir');
35: print $oDir->{Dir}, ' : ' , $oDir->{Sum}, "バックスラッシュn";
36:
37: =head1 説明
38:
39: =head2 getSizeDir($)
40:
41: 指定されたディレクトリに入っている
ファイルの大きさの合計を計算する。 42: 43: =head1 プロパティ 44: 45: =head2 Dir 46: 47: 前回、指定されたディレクトリ名 48: 49: =head2 Sum 50: 51: 前回、求めた大きさの合計 52: 53: =cut
図2●モジュール「My::DirSizeOO」(Dir.OO.pm)
My::DirSizeをオブジェクト指向のクラスを用いて書き換えました。

 また図1や2では,__END__から後ろに,POD(Plain Old Documentation)という形式で利用方法のドキュメントを埋め込んでいます。このようにコードとドキュメントを一緒にすることができますから,ドキュメントだけがどこかにいってしまう心配がありません。これまでperldocコマンドでドキュメントを表示させてきましたが,それらはこのような形で書かれたものだったのです。実際に表示させると写真1のようになります。

写真1●「perldoc My::Dir」の結果
写真1●「perldoc My::Dir」の結果
My/Dir.pmに書かれたドキュメントがヘルプの形式に変換されています。