perlmod - Perl のモジュール (パッケージとシンボルテーブル)
Perlは、他のパッケージの変数によってあるパッケージが壊されるのを
防ぐために、選択的名前空間(alternative namespace)の機構を提供し
ています。実際のところ、グローバル
変数はPerlにはないのです(幾つかの識別子がカレントのパッケージ
ではなく、mainパッケージにありますが)。パッケージ文は compilation
ユニットを与えられた名前空間にあるように宣言します。
そのパッケージ宣言のスコープは宣言それ自身から、宣言を囲むブロッ ク、またはeval、sub、ファイルの終端の最初に現れたものまで
です(my()やlocla()演算子のスコープと同じ)。修飾されていない動的
識別子(dynamic identifiers)はその名前空間に存在するようになりま
す。パッケージ文は(local()を使った)動的変数にのみ効果を持ちます
が、my()によって生成されたlexical変数には影響しません。典型的 には、これはrequireやuse演算子を使ってインクルードされたフ
ァイルの先頭の宣言となります。二ヶ所以上でパッケージを切り替える
ことができます。それによって、ブロックの残りの部分に対してコンパ
イラーが使うシンボルテーブルに影響を及ぼすにすぎません。他のパッ
ケージから識別子にそのパッケージ名とダブルコロンを前置して
$Package::Variableのようにすることで、変数やファイルハンドル
を参照することができます。パッケージ名が空であれば、mainが仮 定されます。つまり、$::sailと$main::sailは等価になります。
古いパッケージ区切り子はシングルクォートでしたが、現在はダブル
コロンを使うのが推奨されています。なぜなら、この方が人間が読みや
すいということと、emacsマクロで読みやすいからです。これはまた、
C++プログラマーに自分が知っていることのように思わせるようにもし
ます。それは以前のシングルクォートがAdaプログラマに馴染みのもので
であったことと同じです。古い構文も互換性のためにまだサポートされて
いるので、"This is $owner's house"のようにすることも できます。これは$owner::sをアクセスします。つまり、 パッケージownerにある $sという変数をアクセスするのですが、これはあなたの望んだ動作では
ないでしょう。
"This is ${owner}'s house"のように ブレースを使うことによって曖昧さを除去します。
パッケージは $OUTER::INNER::var のように、別のパッケージの内
側にネストしておくことができます。しかしながらこれは、名前の検索
に関してなんの仮定も行いません。全てのシンボルはカレントのパッケ
ージにローカルであるか外側のパッケージから完全に修飾されていなけ
ればなりません。
たとえば、パッケージOUTERの中で$INNER::varとしても
$OUTER::INNER::varを参照することはありません。
これはパッケージINNERを分割されたグローバルパッケージとして
取り扱います。
文字(もしくはアンダースコア)で始まる識別子だけがパッケージのシン
ボルテーブルに格納されます。その他のシンボルは、$_のような句読点
変数(punctuation variable)の全てを含め、全てパッケージmainに とどめられます。それに加え、STDIN, STDOUT, STDERR, ARGV, ARGVOUT, ENV,
INC, SIG といった識別子は、たとえ組み込みでない他の目的のた
めに使っていた場合でも強制的にパッケージmainに置かれます。ま た、m、s, yといった名前のパッケージを使っている場合、修
飾形式の識別子を使うことができないということに注意してください。
なぜなら、そういったものはパターンマッチ、置換、変換として解釈さ
れてしまうからです。
(アンダースコアで始まる名前を持った変数は強制的にパッケージ main に置かれるように使われていましたが、アンダーススコアで始めること を、パッケージの作者が変数やメソッド名がパッケージにプライベート なものであることを示すことに使えるようにするのがより便利だろうど 考えてこれを決めました。$_はそれでもグローバルなものです)
eval() された文字列は、eval()
がコンパイルされたパッケージで、コ ンパイルされます。(しかし、$SIG{} への代入は、指定したシグナ ルハンドラーが、パッケージ main
にあるものとして扱います。シグナ
ルハンドラーを別のパッケージにおきたい場合には、そのシグナルハン
ドラー名にパッケージ名を付けてください。)たとえば、Perl ライブラ リの perldb.pl を参照してください。最初に、デバッグしようとす
るスクリプトの変数を、デバッガーが壊さないように、パッケージ DB
に切り替えます。しかし、多くのポイントで、さまざまな式をパッケー ジ main (あるいはもともと指定してたパッケージ) で評価するため
に、一時的にパッケージ main に戻るようにしています。 perldebug
を参照してください。
特殊シンボル__PACKAGE__はカレントパッケージを保持していますが、
変数を構築するために使うことは(簡単には)できません。
my()とlocal()に関連したスコープについてはperlsubを、クロージ ャーについてはperlref参照してください。
パッケージのシンボルテーブルは、パッケージ名に二つのコロンを付け
た名前の連想配列に蓄えられます。つまり、main のシンボルテーブル は%main::、または短く %:: となります。同様に、先に述べたネ ストしたパッケージは %OUTER::INNER:: となります。
ハッシュの個々のエントリの 値 は、*name 記法を使ったときに参
照するものです。実際、以下に例示したものは、最初のものがシンボル
テーブルをコンパイル時に検索するのでより効率が良いものの、同じ効
果を持っています:
local *main::foo = *main::bar;
local $main::{foo} = $main::{bar};
たとえばこれを、パッケージ内のすべての変数を出力するために使うこ とができます。Perl ライブラリ dumpvar.plと CPANNモジュール Devel::Symdumpで実際に行えます。
型グロブに対する代入は、エイリアス操作を行います。たとえば
*dick = *richard;
は、richard という識別子でアクセスできる変数、サブルーチン、ファ
イルハンドルを dick という識別子でもアクセスできるようにしま
す。リファレンスを使えば、特定の変数だけとかサブルーチンだけ、と
いうように個別に別名を付けることができます:
*dick = ¥$richard;
は、$richard と $dick を同じ変数にしますが、@richard と
@dickは 別の配列のままです。解りづらいですか?
この機構は全てをコピーすることを望まないのであれば、cheap なリフ ァレンスをサブルーチンに渡したりサブルーチンから返すために使うこ とができます。これは動的変数に対する代入のときにのみ働き、 レキシカル変数では働きません。
%some_hash = (); # my()にはできない
*some_hash = fn( ¥%another_hash );
sub fn {
local *hashsym = shift;
# ここで %hashsymを通常通り使い、呼び出し側の
# %another_hashに影響を及ぼします
my %nhash = (); # あなたのしたいことを行います
return ¥%nhash;
}
リターンのときに、このリファレンスは*some_hash 型グロブによって 指定されるシンボルテーブル中にあるハッシュスロットを上書きします。 これは、変数の参照外し(dereference)を陽に行うことを考えたくない ようなときに、簡単にリファレンスに関するものを渡すトリッキーなや り方です。
シンボルテーブルの別の使い方は、“定数”スカラーを生成するための ものです。
*PI = ¥3.14159265358979;
この後、$PIを変更することはできません。これはコンパイル時に最適
化が行われる定数サブルーチンとは異なっていて、最適化は行われ
ません。これに関する詳細はperlsubを参照してください。
定数サブルーチンは引数を取らず定数式を返すようになってプロトタイプ
がなされているサブルーチンです。use constantプラグマは定数 サブルーチンを使いやすくします。
*foo シンボルテーブルにある名前やパッケージを探し出すために、
*foo{PACKAGE} や *foo{NAME}とすることができます。これは引
数として型グロブを渡されるサブルーチン内で便利です。
sub identify_typeglob {
my $glob = shift;
print 'You gave me ', *{$glob}{PACKAGE}, '::', *{$glob}{NAME}, "¥n";
}
identify_typeglob *foo;
identify_typeglob *bar::baz;
これは
You gave me main::foo
You gave me bar::baz
を出力します。
*foo{THING}記法は、*fooに属する個々の要素に対するリファレンスを 得るためにも使うことができます。perlrefを参照してください。
パッケージのコンストラクタとデストラクタとして機能する、二つの特
別なサブルーチン定義があります。それは、BEGIN ルーチンと END
ルーチンです。このルーチンでは sub は省略可能です。
BEGIN サブルーチンは、できるだけ早く、つまり、たとえファイル
の残りが解析されていなくても、定義された瞬間に実行されます。ファ
イル内に複数の BEGIN ブロックを置くこともでき、それらは定義さ れた順番に実行されます。BEGIN ブロックは即座に実行されるので、
サブルーチンなどの定義を他のファイルから読み込んでファイルの残り
の部分から見えるようにすることができます。BEGINが実行されれば、
それは即座にundefineされ、使われたコードの全てはPerlのメモリープ
ールに返されます。これはつまり、BEGINを陽に呼び出すことはでき ない、ということです。
END サブルーチンは、できるだけ遅く、つまり、たとえ die()関数
の結果であっても、インタプリターが終了するときに実行されます(しか し、execを使って別のプログラムになったりとか、シグナルによって blown
outするときはそうではありません。(できる ものなら)
自分でトラップしなければなりません)。ファイル内に複数 の END
ブロックを置くこともでき、定義とは逆の順序で実行されます。
つまり、最後に入ったものが最初に出る(last in, first out (LIFO))
ということです。
ENDサブルーチンの内側では、$?はそのスクリプトが exit()
に渡した値が入っています。スクリプトの返す終了コードを変更するた
めに、この変数の値を変更することができます。間違って$?を変え てしまうことに注意してください(たとえば systemを使って何かを 実行するなど)。
Perlに対するスイッチ-n と -pを使った場合、BEGINとEND
は(退化(degenerate)して)awkのそれと同じように、動作するという
ことに注意してください。現状の実装では(変わる可能性はあります)、
-cスイッチによって
構文チェックのみ行われる場合、メインのコードが実行されないのとは 対照的にBEGINとENDの両方のブロックは実行されます。
Perl 5 にはクラスのための特別な構文はありませんが、メソッドとし
て機能するサブルーチンを提供するパッケージはクラスとして機能する
ことができます。そのようなパッケージでは、他のクラス(パッケージ)の
名前を配列 @ISA (パッケージグローバルでなければならず、
レキシカルにはできません)に並べることで、そのクラスからメソッドのいくつか
を引き込んでくることができます。
詳しくは、perltoot と perlobjを参照してください。
モジュールは、同じ名前のライブラリファイルで定義されたパッケージ で、再利用が可能なように設計されたものです。そのモジュールを使用 する任意のパッケージのシンボルテーブルで、自分のシンボルの一部を exportする機能を用意することでこれを行なっているともいえます。あ るいは、モジュールはクラス定義として機能することもでき、陽にシン ボルをexportしなくても、クラスやそのオブジェクトに対するメソッド 呼び出しを通して暗黙のうちに意味が通じるようにすることができます (両方一度に使うことも可能です)。
たとえば Some::Moduleと呼ばれる通常のモジュールを始めるには、以 下のテンプレートを使って Some/Module.pmというファイルを作成しま す:
package Some::Module; # assumes Some/Module.pm
use strict;
BEGIN {
use Exporter ();
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
# バージョンチェックのためにバージョンを設定
$VERSION = 1.00;
# RCS/CVSを使っているなら以下のようにしましょう
$VERSION = do { my @r = (q$Revision: 2.21 $ =‾ /¥d+/g); sprintf "%d."."%02d" x $#r, @r }; # MakeMakerのために、全てを一行で書かねばなりません
@ISA = qw(Exporter);
@EXPORT = qw(&func1 &func2 &func4);
%EXPORT_TAGS = ( ); # eg: TAG => [ qw!name1 name2! ],
# あなたがエクスポートするパッケージグローバルをここに書きます
# 同様にエクスポート可能な関数もここに書きます
@EXPORT_OK = qw($Var1 %Hashit &func3);
}
use vars @EXPORT_OK;
# export しないパッケージグローバルなものをここに
use vars qw(@more $stuff);
# パッケージグローバルを初期化します。最初はexportされているもの
$Var1 = '';
%Hashit = ();
# それからその他のもの(これらは$Some::Module::stuffのようにして
# アクセス可能です)
$stuff = '';
@more = ();
# 全てのファイルスコープを持ったlexicalなものは、関数が使われるよりも
# 前に生成しておかなければなりません
# ファイルにプライベートなlexicalなものはここに置きます
my $priv_var = '';
my %secret_hash = ();
# 以下のものは クロージャーとしてのファイルにプライベートな
# 関数です。&$priv_func として呼び出すことができます。プロト
# タイプを使うことはできません。
my $priv_func = sub {
# stuff goes here.
};
# exportする/しないにかかわらず、全ての関数を作成します。
# {} スタブの中を埋めることを忘れないでください。
sub func1 {} # プロトタイプなし
sub func2() {} # voidのプロトタイプ
sub func3($$) {} # スカラー二つのプロトタイプ
# 以下のものはexportされません。でも呼び出すことはできます!
sub func4(¥%) {} # 一つのハッシュを取るプロトタイプ
END { } # モジュールの後始末コードをここに (グローバルデストラクター)
こうしてから宣言に移れば、関数の中で変数を修飾しないでも使うこと ができます。モジュールの悪性に関する仕組みやスタイルに関する詳細 は Exporter と the perlmodlib を参照してください。
Perlのモジュールは
use Module;
とするか
use Module LIST;
とすることによって、プログラムに取り込まれます。これは、
BEGIN { require Module; import Module; }
や
BEGIN { require Module; import Module LIST; }
とまったく等価なものです。
特殊なケースとして
use Module ();
は
BEGIN { require "Module.pm"; }
と等価です。
すべての Perl のモジュールは .pm という拡張子を持っていて、
use はこれをデフォルトにしていますから、クォートで括って、 ``Module.pm'' と書く必要はありません。これはまた、新しいモジュ ールと古い.pl ファイルや .ph ファイルとに差をつけるのにも
役立っています。モジュール名はプラグマ(``pragma'')として働くもの以
外は、先頭を大文字にします。「プラグマ」は、コンパイラー指令であ
り、「プラグマ的モジュール」(pragmatic module、あるいは古典学者
であれば「プラグマタ」(pagmata)) と呼ぶ人もあります。
require SomeModule;
require "SomeModule.pm";
という二つの文は、それぞれ異なったものです。最初のものは
Some::Moduleのような名前にあるダブルコロンはすべて
使っているシステムのディレクトリセパレーターに変換されます
(通常は“/”)。二番目のものではそうではなく、そういった文字そのもの
として扱われます。そのほかの違いは 最初のrequireではコンパイラーが ``SomeModule''に関して間接的オブジェクト記法を使用し、
$ob = purge SomeModuleは関数呼び出しではなくメソッド呼び出しと
みなします(そう、これが決定的な違いですね)。
use 文はBEGIN ブロックを使っていますから、内容のimport は、
use 文がコンパイルされるとき、ファイルの残りがコンパイルされ
る前に行なわれます。それによってモジュールがプラグマとして機能す
ることができ、また、カレントのファイルの残りの部分でリスト演算子
として参照することのできるサブルーチンの宣言ができるのです。これ は、use の代わりに require を使ったのでは、うまく動きません:
require Cwd; # Cwd:: をアクセス可能にする
$here = Cwd::getcwd();
use Cwd; # Cwd:: から名前をimportする
$here = getcwd();
require Cwd; # Cwd:: をアクセス可能にする
$here = getcwd(); # おおっと! main::getcwd()がない
一般的に言って、use Module () の方が require Module より も推奨されます。なぜなら、そうすることによって
プログラムの実行時ではなく、
コンパイル時にモジュールのチェックができるからです。
二つのモジュールが互いにuseしようとしているときは例外で、
それぞれ他のモジュールから関数を呼び出されます。この場合、
requireしてしまう方が簡単です。
Perlのパッケージは、他のパッケージ名の内側にネストすることができ るので、::を含めたパッケージ名を使うことができます。しかし、
そういったパッケージ名をファイル名として直接使ってしまえば、一部
のシステムでは手に負えなかったり、使うことのできないファイル名と
なってしまうでしょう。したがって、モジュールの名前が
Text::Soundexというものであったとすると、そのライブラリファイ ルは実際には Text/Soundex.pmとして定義されます。
Perl のモジュールは .pm ファイルを常に持っていますが、そのモ
ジュールに対応して動的にリンクされる実行ファイルや、自動ロードサ
ブルーチン定義が存在する場合があります。そういった場合、それらは
モジュールのユーザーからも完全に透過的に見えます。追加機能をロー ドする
(あるいは、自動ロードの準備をする) のは .pm ファイルの責
任となります。POSIX モジュールは、たまたま、動的ロードも自動ロー
ドも行ないますが、使う側は、すべてを使えるようにするために
use POSIX と書くことができるだけです。
エクステンションモジュールの記述に関する詳細は perlxstutと perlgutsを参照してください。
標準ライブラリやCPANと同じくらい説明されているPerlのモジュールと クラスに関する一般的なスタイルについてはperlmodlibを参照して ください。Perlの標準 import/export 機構がどのように動作している のかはExporterを、クラスの作成に関する in-depthなチュートリア ルはperltootを、オブジェクトに関する hard-core リファレンスの ドキュメントはperlobjを、関数とスコーピングの説明はperlsub をそれぞれ参照してください。