Perl Perl_6
Perl package on perlmod パッケージ (d058)
目次 - Perl Index
Theme
Perl について、復習を兼ねて断片的な情報を掲載して行く連載その d058 回。
Perl で、「 alternative namespace 」( 選択的名前空間 ? 代替名前空間 ? ) のメカニズムを提供するというディレクティブ「 package 」を確認します。
今回は前回 (d057) 確認したドキュメント perlmod から、「 package 」に関わる部分を抜粋して確認します。
名前空間
Perl では package によって名前空間を分割することで、それぞれの名前空間 ( package ) に存在する名前が相互干渉することを防止しています。
名前が相互干渉しないということは、例え同じ名前の変数が存在しても、それが異なる package にあるなら、基本的に別の変数として問題なく利用出来るということです。
package は、ディレクティブ「 package 」を利用した package 構文によって任意に指定出来ます。
package any_pack_01;
# start パッケージ any_pack_01
...
# end パッケージ any_pack_01
package any_pack_02;
# start パッケージ any_pack_02
...
# end パッケージ any_pack_02
package main;
# start パッケージ main
...
# end パッケージ main
ディレクティブ「 package 」を利用しない場合は、暗黙的にファイル全体が package「 main 」として機能します。
前述したとおり、各 package の変数は異なる名前空間で管理されます。Perl の名前空間は (d004) で確認した「 シンボルテーブル 」によって管理されます。
package の範囲
package の範囲 ( スコープ ) は、 package 宣言から記述の終わりまでを囲む「 ブロック 」または 「 eval 」および「 ファイル 」のいずれかになります。
また、前項の例示のように、package 構文そのもの ( 暗黙の「 { } 」ブロック ) で範囲を規定することも出来ます。
基本的に、それは演算子「 my() 」や「 local() 」で宣言するスコープと同じですが、「 my() 」等でそのスコープ ( 利用範囲 ) が限定されていない変数があった場合、その変数の最大のスコープは peckage 単位になります。
package 構文による package 宣言がない場合は、デフォルトで package「 main 」として機能しますので、「 my() 」等で修飾されていない変数の最大スコープは自動的に 1 つのファイル内に限定されます。
そういうわけで、Perl には本当の意味での「 グローバル変数 」は存在しないそうです。
perl - myとourとscopeと - 404 Blog Not Found も合わせて参照してみましょう。
また、package のスコープは、個別のコンパイル単位 ( the compilation unit ) として扱われます。
任意の package の識別子を参照する
package 名および識別子を「 :: 」( double colon ) で連結することで、任意の package に存在する識別子を参照することが出来ます。
例えば、package 名が「 Package 」で変数名が「 $Variable 」だった場合は、「 $Package::Variable 」でそれを参照します。この場合の「 Package 」は「 パッケージプレフィクス 」とも呼ばれます。
package 名 ( パッケージプレフィクス ) を省略して「 $::Variable 」とした場合は、package 「 main 」が対象になります。つまり、「 $main::Variable 」と等価です。
現在の主流はこのように「 :: 」を package 名と識別子のデリミタに使用することですが、古いバージョンの Perl では、「 $Package'Variable 」のようにデリミタとして「 ' 」( single quote ) が使われていました。
「 ' 」によるセパレートは、後方互換のために現在でも有効です。
そのため、次のような記述はあなたの希望する結果にはならないかもしれません。
# Oops !
print "This is $owner's house\n";
なぜなら、「 $owner's 」が package「 owner 」のスカラ「 $s 」へのアクセス、つまり「 $owner::s 」を意味することになるからです。
こうした罠にはまったら、つぎのようにして対応します。
# { } で曖昧さを除去
print "This is ${owner}'s house\n";
# or
# \ で ' をエスケープ
print "This is $owner\'s house\n";
なお、デリミタ「 :: 」は「 C++ 」プログラマに、デリミタ「 ' 」は「 Ada 」プログラマに馴染みがあるようです。
また、「 $OUTER::INNER::var 」のように package 名を入れ子にすることも出来ますが、例えば「 $OUTER::INNER::var 」と「 $INNER::var 」は異なる package を示します。
これは、Unix 系 OS のシステムパスで「 /OUTER/INNER/var 」というファイルと「 /INNER/var 」というファイルが異なるファイルであることに似ています。
ただし、システムパスの相対パスに相当する機能は Perl package にはありません。
package と識別子
通常任意に指定した package のシンボルテーブルには、「 文字 」または「 _ 」( under score ) で始まる識別子のみが格納されます。
それ以外の識別子、例えば「 $_ 」のような句読法変数 ( デフォルトの組み込み変数 ) 等は package「 main 」のシンボルテーブルで維持されます。
加えて、修飾されていない特別な識別子も同様に package「 main 」で維持されます。
それは「 STDIN 」, 「 STDOUT 」, 「 STDERR 」の STD シリーズ (0x42) や、「 ARGV 」 (0x3b), 「 ARGVOUT 」, 「 ENV 」 (0x53), 「 INC 」 (0x8e) それから「 SIG 」(0x267) といったものです。
それから、package の呼び出し時に識別子「 m 」, 「 s 」, 「 y 」は利用出来ません。なぜならこれらは、パターンマッチ ( m ), 置換 ( s ), 変換 ( y ) として Perl に解釈されるからです。
識別子 ( 変数名 ) についての詳細は "The Syntax of Variable Names" in perlvar を参照します。
なお、特別な識別子「 __PACKAGE__ 」はアンダースコアで始まりますが、これは現在の package 名を格納するようになっているので、通常は任意の変数名に使うことは出来ません。
NEXT
次回は、perlmod から「 シンボルテーブル 」に関する部分をまとめてみます。
参考情報は書籍「 続・初めての Perl 改訂版 」, 「 Effective Perl 第 2 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。
目次 - Perl Index
Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)