Perl入門 ≫ LESSON10 パッケージ・モジュール

他のファイルのプログラムを読み込む

Perlプログラムでは、他のファイルに書いたプログラムを読込んで使用することができます。
一番楽な方法は次のように読込むことです。
読み込むにはrequire を使います。

require "ファイル名";

では実際にやってみましょう。

こんなファイルがあるとします。
req1.plという名前にしましょう。

my $test = "test\n";
sub sub1 {
    print "sub1 exec $test\n";
}

そしてプログラム中で次の様に使います。

require "req1.pl";

&sub1();

結果は以下。

sub1 exec test

プログラムを実行すると、他のファイルにあるサブルーチンが実行されます。
こうすれば、よく使うサブルーチン等は一々書かなくても、1つのファイルに定義しておいて、使うときにそのファイルを読み込むだけで使うことができます。

この時読込むファイル名は、とりあえず同じディレクトリにあれば問題ありません。
違う場合はパスをちゃんと指定して読込みましょう。

パッケージ

Perlでは、パッケージというものを利用して、別々の名前空間を利用し変数が干渉しあわないようにしています。

なんだかわけがわからないかもしれませんが、簡単に言うとこんな状況の時に使うことになります。
今、二つのプログラムがあるとしましょう(ファイルは別々)。この二つを組み合わせて別のプログラムを作ります。
が、この二つのプログラムでは同じサブルーチン名や同じ変数名を使ってあります。
よって、二つのプログラムを単に一つのファイルに結合してそのまま使ってもすんなり動きません。

この時、二つのプログラムをそれぞれパッケージ化すれば、そのまま使うことができます。

####req1.pl

#パッケージreq1宣言
package req1;
our $test = "test\n";
sub sub1 {
    print "req1 sub1\n";
}

####req2.pl

#パッケージreq2宣言
package req2;
our $test = "test2\n";
sub sub1 {
    print "req2 sub1\n";
}

使い方は次のようになります。

package パッケージ名;

使い方:
$パッケージ名::変数名
&パッケージ名::サブルーチン名

各ファイルの最初に「package パッケージ名;」とパッケージ宣言をすると、そのファイルの終わりまでが独自の名前領域をもちます。
よって、プログラム中でこの二つのファイルを読み込んで使っても、それぞれのパッケージ名が違うので変数・サブルーチン名が同じでもちゃんと動きます。

使う時はそれぞれ変数とサブルーチン名の前に”パッケージ名::”を付けて指定してやる必要があります。

require "req1.pl";
require "req2.pl";

#パッケージreq1のサブルーチンsub1を実行
&req1::sub1();
#パッケージreq2のサブルーチンsub1を実行
&req2::sub1();

#パッケージreq1の変数を参照
print "$req1::test";
#パッケージreq2の変数を参照
print "$req2::test";

変数宣言の前、myじゃなくてourになっています。注意しましょう。説明はあとで。
結果は以下。

req1 sub1
req2 sub1
test
test2

多少警告が出ますが気にしないでいきましょう。
結果の最初の2行は、各サブルーチンsub1を実行した結果で、最後の2行は各変数を参照しています。

used only once

Warningで

Name "req2::test" used only once: possible typo at ~

と出ると思います。
これは、

この変数は一度しか使われていないよ?ミススペルじゃないの?

といってます。
余計なお世話です!!

テストスクリプトなんかだと中身が単純なので、よく出てくることがあります。 面倒なので、スクリプトの最初に

use warnings;
no warnings qw(once);

と入れます。
use warningsは、Perlプログラム警告を有効にするかを制御するものです。
実行時の-wオプションでもほぼ同じですが、スクリプトに書いておいたほうがいいよいうなので、推奨されています。
use strictと同様にセットで必ず書いておいてもいいかもしれません。



モジュール

Perlで再利用されるソフトウェア群をモジュールと言います。
ここでは難しいことは置いといて、とりあえず基本的な使い方を学習しましょう。

何か便利なサブルーチン群をファイルに保存し、色々なプログラム中で使えるようにします。 モジュールは、そのモジュールが書かれたファイルをプログラム中で読込んで使います。
上で使ったreq1.plやらreq2.plもお粗末ながらモジュールと言えます。
が、正確にはモジュールファイルは拡張子を”pm”にする必要があります。

使い方は、上でやったrequireのほかにもう一つ、useを使う方法があります。

require "ファイル名";

use モジュール名;

このモジュール名は、モジュールファイルXXX.pmの拡張子を取った名前XXXと書きます。

注意

requireではファイルはパス指定で読込むことができますが、useで指定するのファイルは決められた場所にしか置いておくことができません。 とりあえず同じディレクトリにあれば問題なく使えます。(詳しくは後で)

また、PC環境でrequireを使う時に注意しなければならないのは、

require "bin\req.pl"

とやってもできません。
Perlでは”\”はエスケープの意味で使われてしまうので、ディレクトリの区切りを表すには”\\”としなければなりません。
よって、

require "bin\\req.pl"

が正解。または、

require "bin/req.pl"

でも問題ありません。



この二つの違いは何かと言うと、 requireを使うと、プログラムの実行時に読み込みを行います。
useを使うと、コンパイル時に読み込みを行います。つまり、読込むモジュールが存在しない場合、 useだとプログラムの実行さえ行ってくれません。

では実際にやってみましょう。

####req1.pm

package req1;
our $test = "test\n";
sub sub1 {
    print "req1 sub1\n";
}

####req2.pm

package req2;
our $test = "test2\n";
sub sub1 {
    print "req2 sub1\n";
}



使ってみましょう。

use req1;
use req2;

&req1::sub1();
&req2::sub1();
print "$req1::test";
print "$req2::test";

結果は以下。

req1 sub1
req2 sub1
test
test2

パッケージ名とモジュールファイル名は別物です。
useで使うのはあくまでもモジュール名。つまりファイルの”.pm”拡張子を取った形です。
が、ファイルの中で指定するパッケージ名は別の名前でもかまいません。
ですが、混乱を避けるために同じ名前にする場合が多いです。

変数の範囲

上のプログラムの変数宣言の前にmyのかわりourを使いましたが、myにすると、パッケージの変数を認識してくれません。

実は変数には有効になる範囲があり、前につけるものによって有効範囲が違います

変数範囲の種類
myスコープ内({ }の間)で参照可能
localグローバルな変数があるときは一時避難
ourパッケージ内の変数
スコープの外でもパッケージ名をつけて参照可能


myをレキシカルスコープ宣言、localとourをグローバル宣言といいます。
グローバル宣言のついた変数はプログラムのどこからでもアクセスできますが、myは{ }の間でのみ通用します。{ }の中で宣言したものは、その外からはアクセスできません。

my $test = "test\n";

print $test;
sub1();
print $test;

sub sub1 {
    my $test = "test2\n";
    print 'sub1 ' . $test;
}

sub1関数の中の$testはこの関数の中でのみ有効です。この値を外から見ることはできません。外で定義している$testとは別物なので、sub1関数の呼び出しが終っても、外の$testの値はかわりません。

test
sub1 test2
test

もしsub1関数の中の$testの前にあるmyをとると、外にある$testに新しい値を代入していることになるので、3っつめの出力結果は「test2」になってしまいます。

パッケージにある変数を外から使う場合は、ourを付けて宣言します。

ではlocalとはなんでしょう?
local宣言した変数は、同じ変数のグローバル変数の値をスコープ内の間だけ一時的に書き換えます。

our $test = "test\n";

sub2();
sub1();

sub sub1 {
    local $test = "test2\n";
    sub2();
}

sub sub2 {
    print $test;
}

test
test2

sub2関数では外で定義した$testの値を出力しています。
sub1関数の中でsub2関数をよんでいますが、sub1関数で$testがlocal定義されたので、この中では$testの値は「test2」になります。そのため、同じsub2関数の呼び出しでも出力値が異なります。
ちなみに、$testの値は一時的に置き換わっただけなので、最後にもう一度sub2();を実行すると、「test」が出力されます。


ページのトップへ戻る