Synopsis 10:パッケージ
Larry Wall <larry@wall.org>
Created: 27 Oct 2004 Last Modified: 9 Jul 2010 Version: 13
この概要は、一度も書かれたことがなかったにもかかわらず、パッケージを論じる Apocalypse 10を要約する。
Perl 5 のように、パッケージはモジュールとクラスのベースだ。 5、モジュールとクラスがそれと共に宣言される Perl の場合と異なり別のキーワード、しかしそれらは余分の行動でまだただパッケージに過ぎない。 同じく、たとえ使われていないとしても、すべての typename が関連づけられたパッケージネームスペースを含む。
普通のパッケージが宣言されるでpackage キーワード。 Perl 5 の場合と異なり、 Perl 6 にそれはただブロックで使われることができるだけだ:
package Bar {...} # block is in package Bar
宣言がそうすることができる名前付きパッケージがただ名指されたサブルーチン宣言のように、展開式の一部として起こる。
特別な例外として、もし braceless であるならpackage 宣言が最初の実行可能ファイルとして起こる、ファイル、それからそれの文はファイルの残りが Perl 5 コードであることを意味するとみなされる。
package Foo; # the entire file is Perl 5 ...
このフォームは Perl 6 ファイルで非合法だ。 もしあなたファイルによってスコープ宣言されたパッケージを持っているために、あるいは、ブレース形式を使え、あるいはそれを宣言しろといいのにと思うmodule その代わりにキーワード。
Perl 6 に barewords がないから、パッケージ名が前もって申告されなくちゃならないか、あるいはシギルのような(人たち・もの)を使う::PackageName 構文が型が何か他の方法を与えられるであろうことを示す。 :: それが Perl 5 にする(とき・から・につれて・ように)、接頭辞が globalness を暗示しない。 (使用GLOBAL:: それのために。)
A bare package 宣言詞(明示的な範囲宣言詞なしでそんなものけれどもmy)宣言するour 現在のパッケージ(あるいはモジュール、あるいはクラス、あるいはロール、あるいは...)の中のパッケージ。 使用GLOBAL:: 世界的なパッケージ名を申告するために。
レキシカルにスコープ宣言されたパッケージ、使用を宣言するためにmy package.
あなたがいずれかを使うことができる匿名のパッケージを宣言するために
package {...}
package :: {...}
ファイルが解析され始めるすべてGLOBAL
実装が、けれども、最初の package-ish 宣言に依存している何か他のパッケージスコープに変わるかもしれない。 もしパッケージ変形、それから解析をすることが変わるその最初の宣言ではないであるなら「main」 Perl のために5つのコードをパッケージする. Perl 6 コードが留まるGLOBAL その状況で。 コードが次の通りの主回線GLOBAL さもなければ宣言されないなら、ネームスペース。
トレイトが使ってセットされる Package is:
package Foo is bar {...}
シンボリックリンクが一緒にされるすべて::($expr) どこでもどんな変数でも、パッケージ、モジュール、あるいはクラス名で正当な構文::Ident 正当だ。 展開式によって返された文字列は賛成で解析されるだろう:: subpackage 名を示す。 これを混乱させるで
Foo::{$key}
あなたに特定のシンボルテーブルでルックアップをさせる構文。 この場合、ではないが(そのために)解析をしたキー::. それはただハッシュルックアップに過ぎない。
すべてのパッケージ本体(モジュールとクラスを含めて身体)はそれらが埋め込みであるコードの標準の実行時間に実行する。 標準の主回線コードで、これは実行の通常フローだ;もしこれが初期化されるにはあなたが欲するパッケージで何かを初期化するには遅すぎであるなら、呼び出されるメインサブルーチンの使用が指定期間の末の正常実行だと見なせ。
宣言して見るMAIN S06 の中のサブルーチン > 。
主回線コードから独立したファイルで定義されたパッケージ(モジュール、クラス、ロールなど)のために、定義上主回線コードがあり得ない、しかし、ものが初期化を必要とする場合に備えて、中古のモジュールの中のトップレベルのコードはある時点で実行される必要がある。 コードがモジュールの中で観念的にポイントでよりさらに遅くではなく起きるこの擬似主回線の祈りuse あるいはneed コンパイルのプロセスでの呼び出し、しかし、モジュールが何度その後コンパイルで使われるかにかかわらず、モジュールはただ1度だけ実行されてそれがそうである必要があるコードが十分に面白くないと考えられるということだ。 (実際、もし若干の前のコンパイルの点の結果がキャッシュされたなら、それはまったく走る必要がないかもしれない。)
もし意味で点から点まで変動するコードを持っていることが望まれるなら、あなたはこのようなコードを INIT ブロックに入れるべきだ。 (同じく、あなたはコードをコンパイルからコンパイルまで首尾一貫しない意味規則を持っている、しかしおそらく良くない考えである CHECK ブロックに入れることができた。)
いずれにしても、他のユーザーから、コンパイル順序あるいは他のダイナミックな情報に関してそのユーザーのどんな知識ででも依存する外部モジュールが同じくこの一つの「最初の使用」の実行で依存して、そして一貫した意味規則を期待するかもしれないことは何のためにでも誤っている。 (本当に、依存がそうであるべきであるほど dynamic が標準のパラメータとしてあるいは動的変数としてあなたのモジュールのルーチンあるいはメソッドにランタイムにパスしたすべて。 例えば、あなたはモジュールコンパイル時間にあなたの呼び出し側が「致命的な」意味規則を使っているだろうかどうか知ることができない。 それはダイナミックにスコープ宣言されたインフォメーションだ。)
もしあなたがもし呼び出されるなら余分の何かをするモジュールをスタンドアローンであるようにすることを望むなら、もしモジュールがただ使われて / ほかのところに必要とされるなら、無視されるであろうメインサブルーチンを定義しろ。
形式のどんなオブジェクトでもの宣言A::B::c 同じく(もし必要なら)空のパッケージを作成するAそして空のパッケージB 内部A作ることのほかにc 内部B. パッケージがその後であるかもしれないほど空きは何としてでも再び申告される、再宣言警告ではなく、他のパッケージのようなオブジェクト(モジュール、クラスなど)がこのような再宣言のために表示されるだろう。 もし親パッケージがすでに存在する、切り株パッケージが作成される必要がないなら、そして形式の宣言はなしA::B::c 実装の型について言うべき何でも持っているA あるいはパッケージA::B、どんなパッケージ変形からでもネーミングのことの目的でパッケージとして作用することができる。
離れてパッケージ宣言構造について、パッケージ名が常に一番奥の、から最も外側のレキシカルスコープから捜される。 もし確定ではなくがレキシカルスコープを取り巻いている何、パッケージででも現在のパッケージから捜されるなら上へパッケージを含むことを通してそうするためにGLOBAL. もしそれがそうじゃないなら、見いだされて、コンパイラエラーが結果として生じる。
イニシャルと同じように::プレゼンスの:: 名前以内は(Perl 5 の場合と異なり) globalness を暗示しない。 真のグローバルが常に入っているGLOBAL:: ネームスペース。
PROCESS:: プロセス、が観念的に外の中ですべてのインタープリタによって共有されるネームスペースGLOBAL::、パッケージ捜索以外そこ(に・で)何かを探さない。 (文脈上の変数捜索がそうする;$*PID 最終的に居所を定めるだろう$PROCESS::PID もし内部の callframe のによって隠されないなら$*PID.)
パッケージ(あるいは他のいかなる類似のネームスペースでも)が自動的に荷を積むことを管理することができる。
しかしながら、 Perl 5 のAUTOLOAD 宣言を鮮明度から区別する、しかし sub を宣言するように制限されない MMD オートローダによって取って代わられている。 宣言詞多潜水艦が申告される実行時:
multi CANDO ( MyPackage, $type, $name, *%args --> Container)
それはコンテナの宣言のためにインチのためにもう1つのコンテナ・オブジェクトの中のオブジェクトをおごる;誰もパッケージ(あるいはモジュール、あるいはクラス)で名前を捜していて、そして名前がすでにパッケージで存在しないとき、それは呼び出される。 (特に、.can 呼び出しCANDO
クラスが特定のメソッドをサポートするかどうか決定しようとするとき。)
そうするための引数CANDO コンテキストにどんな種類のオブジェクトが期待されるかについての型情報を含めろ、さもなくばこれは求められた名前から直感で知られるかもしれない。 何ででも場合が、そこ(に・で)多数であるかもしれないCANDO ディスパッチされるルーチンは MMD として :
multi CANDO ( MyPackage, Item, $name, *%args --> Container) multi CANDO ( MyPackage, Array, $name, *%args --> Container) multi CANDO ( MyPackage, Hash, $name, *%args --> Container) multi CANDO ( MyPackage, Code, $name, *%args --> Container)
それがコンテナ・オブジェクトだから、パッケージ自身はちょうど最初の引数とパスされる。 次の引数が内部のコンテナと(それによって)オブジェクトが外のコンテナで調べられるはずである「名前」あるいは「キー」の望ましい型を識別する。 このような名前がそのコンテナ名を含まない、 Perl と異なり、5がマジカルだ$AUTOLOAD 変数。
同様にそれはコードオブジェクトの「ロングネーム」の型情報を含まない;この情報は型パラメータとしてであるという状態で入ってきて、そして、普通の subsignature マッチングを使うことに対して、マッチされるかもしれない:
multi CANDO ( MyPackage, &:($), $name, *%args --> Container) # 1 arg multi CANDO ( MyPackage, &:($,$), $name, *%args --> Container) # 2 args
素晴らしい(人たち・もの)%args ハッシュは標準的な Perl 6 使用で空である可能性が高い、しかし Perl の若干の方言がメカニズムが追加の文脈上の情報でパスすることを望むだろう、それでこのパラメータがこのような目的に限られることは可能だ。
CANDO 適切なソート(すなわち変数、サブルーチン、あるいはメソッドオブジェクト)の内部のコンテナオブジェクトを返すために期待される、あるいは、いい加減に、「autovivify する」ことができるプロクシオブジェクトあるいはNil もし存在するその名前ではないが見なしたなら問題のネームスペースに宣言された。
(ただそのままのだけだNil 「そこに」、それ以来タイプされた undefs が autovivifiable 代理オブジェクトとして機能しないかもしれない(とき・から・につれて・ように)、解釈される。 S12 を見ろ。)
宣言はただ新しいオブジェクトへのインタフェースを定義する。 けれどもオブジェクトが、まだ、完全に定義されている必要がないことCANDO ルーチンが確かに熱心にそれを定義して、そして、もしそれが宣言をキャッシュすることを望むなら、外のコンテナ(シンボルテーブル)の中に内部のオブジェクトをインストールしさえすることを可能にされる。
それがまだ知られていないかもしれない宣言時間で内部のコンテナオブジェクトが左辺値あるいは右辺値コンテキスト;委任状の使用で使われるであろうかにかかわらずオブジェクトが後に読み取り専用あるいは rw 意味規則を供給することができる。
問題のパッケージがクラスであるとき、実数メソッドあるいは submethods を宣言することは同じく可能だ:
multi method CANDO ($self: Code, $name, *%args --> Container) multi submethod CANDO ($self: Item, $name, *%args --> Container)
メソッド形式はサブクラスによって継承される。 Submethods は決して相続されない、しかしクラスの中でまだ MMD をするかもしれない。 (普通の多潜水艦がただネストされたレキシカルスコープによって許された程度に「相続される」。)
問題のパッケージがクラスじゃないとき、 Perl 6 が関数のためにもうデフォルトによってパッケージを調査しない限りにおいて、わずかな問題がある、ただレキシカルスコープだけ。 しかしながら、我々はまだ能力のように dynamic にパッケージに関数を加えるだろう、それで語彙の限界の周りに取るべき2つの方法がある。
あなたが持っている推定している最初CANDO それはあなたの現在のパッケージに付け加える、あなたはただ明示的に現在のパッケージとしての新たに造り出されたサブルーチンを呼び出すことができる:
OUR::($somename)();
これは完全に語彙のネームスペースを迂回する。 代わる代わる、我々は機構を準備することができるそれによって、あなたが輸入するか、あるいは定義するもしCANDO 所定のレキシカルスコープの中に、その範囲の中からのすべての呼び出しは場所のリストに現在のパッケージを加えるフェイルオーバを登録する、からサブルーチンを探せ(あるいは、明らかに呼び出しCANDO 最後の手段としてそれの後に). レキシカルに存在することに対する影響がからそれらを含めて、定義をスコープ宣言したパフォーマンスがないCORE. このアプローチは機能名を見いだすことに関しての失敗がコンパイル時間に報告されることができない、しかしその代わりにランタイムまで遅れているに違いないことを要求する。
もう1つの潜在的な不利がパッケージのシンボルが同じくあなたの外のレキシカルスコープで定義されたすべてのシンボルによって尾行されるということだ、それは下記を含むCORE. もしこれが問題であるなら、直接を使えOUR 上の呼び出し。
それを見るもう1方法はそれほど語彙的だCANDO 関数ディスパッチャーの検索の終わりにそれ自身を加えるが、それ自身のすぐ前に検索パスで新たに定義された関数の間一種のキャッシュとして現在のパッケージを準備する。