タイトル

Synopsis 13:多重定義

著者

Larry Wall <larry@wall.org>
 

機種

Created: 2 Nov 2004

Last Modified: 25 Oct 2010
Version: 15
 

概観

この概要は Apocalypse 13にあるべきであった Apocalypse 12のそれらの部分を論じる。

多数のディスパッチ

Perl 5 の多重定義メカニズムは Perl 6 の多数のディスパッチメカニズムによって取って代わられた。 関数が定義される内部のほとんどすべてmulti sub あるいはmulti 一般的な型の上のメソッド。 組込み演算子が代わりの呼び出し構文でただ奇妙に関数と命名される。 あなたがそれらに負担をかけ過ぎるためにしなければならないすべてはあなた自身のものを定義することだmulti いっそう特定の型で引数の手術をする sub とメソッド。

なぜなら単項の演算子、これは効果的な相違をほとんど作らないが、2進法の演算子、多数のディスパッチのために左の引数の型にだけ注意を払うことについての Perl 5 問題を直す。 両方の引数型がどのルーチンを呼び出すべきか決めるのに使われる、もう何もないから左の(の・もの・人)の代わりに右の引数の型を使うために引数を交換することを必然的に必要としている詐欺。 そしてもうなかった、何かが引数が反転させられたかどうか見るために特別な旗を調べる必要がある。

はるかに多くのために多数のディスパッチについて、 S12 を見ろ。

構文

特別なもう何もないuse overload 宣言から独立した構文のmulti ルーチン自身。 存在する組込み sub に負担をかけ過ぎるために、何かを言え:

multi sub uc (TurkishStr $s) {...}
 

Amulti もし書き出される proto によって支配されるなら自動的に輸出される。 それは同じく明示的に輸出されるかもしれない:

multi sub uc (TurkishStr $s) is exported {...}
 

今もしあなた呼び出しuc() 何に関してでもトルコの文字列、それは組込みの(の・もの・人)よりむしろあなたの関数を呼び出すだろう。

パラメータの型は何の longname にでも含められるmulti sub あるいはメソッド。 それでもし、あなたが種々のスラーを扱うことができるように、あなたがアラブの文字列のために文字列結合に負荷をかけ過ぎることを望むなら、あなたは言うことができる:

multi sub infix:<~>(ArabicStr $s1, ArabicStr $s2) {...}
multi sub infix:<~>(Str $s1, ArabicStr $s2) {...}
multi sub infix:<~>(ArabicStr $s1, Str $s2) {...}
 

use overload それが同じサービスルーチンにエイリアスのいくつかの異なった演算子に容易であったという点で、構文が Perl 6 の構文にわたって1つの利益を持っていた。 これは容易に Perl 6 のエイリアシングで扱われることができる:

multi sub unimpl (MyFoo $x, MyFoo $y) { upchuck(); }
&infix:<+> ::= &unimpl;
&infix:<-> ::= &unimpl;
&infix:<*> ::= &unimpl;
&infix:</> ::= &unimpl;
 

それは1つの解決だ、しかししばしばあなたの代替物はすべて同一名を持って、そしてその代わりにそれらシグネチャーの点で異なる。 若干の演算子が可換であるか、あるいはさもなければ、1以上のオーダーでそれら引数をとることができる。 Perl はあなたにパターンがあなたが宣言したかのように合った体とこれらがであろう既定の事実のための多数のシグネチャーがマルチ項目を分離すると宣言することを許す。 もしあなたが言うなら:

multi sub infix:<+> (Us $us, Them $them) |
                    (Them $them, Us $us) { myadd($us,$them) }
 

それは同等の値:だ

multi sub infix:<+> (Us $us, Them $them) { myadd($us,$them) }
multi sub infix:<+> (Them $them, Us $us) { myadd($us,$them) }
 

それ以外たった1つの体が本当にある。 もしあなたが宣言したならstate 変数は体の中で、例えば、そこ(に・で)ただそれらの1つだろう。

Amulti ただそれが定義されるか、あるいは輸入されるスコープの中で実施される。 一般にあなたは置かれてそうすることを望むあなたmulti それらであるところはどこでも、輸入されるであろうパッケージの中への sub が必要とされる。

あなたが多数のシグネチャー構文を使うとき、代わりのシグネチャーはすべて正式の変数名の同じセットをバインドするように要求されない、同様に同一性とバインドすることを必要とされるすべての名のパラメータはそうじゃない。 自由にされたパラメータは未定義の値で(たとえそれらがデフォルトを持っているとしても)発生するだろう。 何のためにでも同一でない名目上の型、意志が名目上の型で宣言した実際の語彙の変数で多数のシグネチャーで生じるパラメータMuそしてもし自由にされるなら、意志を含む段落Mu.  引数名タイプミスを捕えるために、コンパイラは未使用のパラメータについて警告するかもしれない。

推測:もしそうする最初のパラメータmulti シグネチャーがインボカントコロンによって後に続かれる、そのシグネチャーは2つのシグネチャー、普通のメソッド定義のための(の・もの・人)と文通することのための(の・もの・人)を表すmulti コロンの代わりにコンマを持っている鮮明度。 このフォームは正当だ、ただ標準的なメソッド鮮明度が正当、そしてただもしだけだろう、何でも型を宣言したところがパラメータがそれと一貫している最初の$?CLASS.

次候補

ルーチンがもう定義されるかどうかに関係なく、ディスパッチはルーチンのシグネチャー宣言に基づいている。 もし試みが、宣言されたが、未定義のルーチンに、 Perl が再び急送するであろうディスパッチにそうさせられるならAUTODEF 適切にルーチンを定義するサブメソッド[推測]。 これは次候補に実行時メカニズムを提供する。 デフォルトまでに、これらの宣言は額面通りに信用されて、そして意味規則の基礎となっている何も指定しない。 そんなもの、それらが「浅はかな」解釈であるように。

[注意しろ:「深い」に関する次のセクションはもうメタ演算子が今作成される方法という条件のもとで必要じゃないかもしれない。]

しかしながら、時々あなたはあなたの演算子の「深い」通訳を指定することを望む。 すなわち、あなたは種々の浅い演算子によって使われるかもしれない抽象的な演算を指定している。 Any の深い多宣言が論理的にそれに基づき得るすべての浅い演算子の中に「拡大される」だろう。 もしあなたが言うなら:

multi sub infix:<%> (Us $us, Them $them) is deep { mymod($us,$them) }
 

それから

multi sub infix:<%=> (Us $us, Them $them) { $us = $us % $them }
 

あなたのために(あなたがあなた自身それを定義しないなら)同じく生み出される。 定義がコントロールされる sub へのマジカルな名前のマッピング%?DEEPMAGIC コンパイラハッシュ。 Pragmas はレキシカルスコープに関してこのハッシュの内容物に影響を与えることができる、それであなたはマジカルな自(己・動)世代で異なったポリシーを持っていることができた。 デフォルトマッピングは Perl 5 多重定義のスタンダード次候補マッピングに対応する。

これらの深いマッピングは主に(彼・それ)らのすべての変形に名前をつけることが容易にできないであろう2項演算子のために意図されている。 Prefix 演算子がより単純である傾向がある;特にそれに注意しろ

multi prefix:<~> is deep {...}
 

もっと良く書かれる:

method Stringy {...}
 

(下を見ろ)。

型配役

クラスがそれが、それがルーチン、配列、あるいはハッシュであるかのように、反応することを可能にするメソッドを定義するかもしれない。 長いフォームは次の通りだ:

method postcircumfix:<( )> ($capture) {...}
method postcircumfix:<[ ]> (**@slice) {...}
method postcircumfix:<{ }> (**@slice) {...}
 

それらは少し実用的じゃない、それであなたは同じくこれらの短いフォームを使ってもよい:

method &.( $capture ) {...}
method @.[ **@slice ] {...}
method %.{ **@slice } {...}
 

これらの短いフォームでのシギル - ドットの連続はシギル - ドットで、まったく同じ方法でそれで、対応する公共の演算子を自動的に生成する:

has $.action;
has @.sequence;
has %.mapping;
 

公共のアクセス機構メソッドを自動的に生み出す。

そしてそれが同じメソッド - 自(己・動)生成機構を使うから、特定のシギルは、それがドットとシグネチャーを含んでいる括弧のペアによって後に続かれる限り、短縮フォーム後置接周辞演算子が・・・実際に重要じゃないことを明示したものだった。 (括弧のそれぞれの型のために「自然の」シギルに忠実であることがあなたのコードの未来の読者におそらくもっと親切であるけれども)

それほど角括弧的なメモが形式を添え字化する.<a b c> 自動的にそうするためにそれ自身を呼び出しに翻訳する .{'a','b','c'} 角度のためにメソッドを定義することは基本的に役に立たないように。

期待された意味規則の&.() 新しいオブジェクトを作るかもしれない、あるいはそうしないかもしれない型威圧政治のそれだ。 それでもしあなたが言うなら:

$fido = Dog.new($spot)
 

確かにそれ作る新しいDog オブジェクト。 けれどももしあなたが言うなら:

$fido = Dog($spot)
 

それは電話をするかもしれないDog.newあるいはそれ引くかもしれないDog 犬から Spot の身元でキャッシュ、あるいはそれが絶対的にゼロのもしをするかもしれない$spot すでにどのようにそうであるべきか知るDog.  後退として、ない場合メソッドが強要のリクエストに返答する、クラスはしようと試みるように求められるだろうDog.new($spot) その代わりに。

他方の端から強制型変換を指定すること、すなわち、クラスでどのように何か他のクラスへのその値の1つを強制するべきか明示することは同じく可能だ(そしてしばしば望ましい)。 もしあなたがその名前が宣言型であるメソッドを定義するなら、それは威圧政治としてその型に連れて行かれる:

method Str { self.makestringval() }
 

すべてのメソッドと同じように、あなたは同じく文通することを輸出することができるmulti

multi method Str is export { self.makestringval() }
 

どのケースかについてあなたはフォームを呼び出して両方ともを使うことができる:

$x.Str
Str($x)
 

もしソースクラスと目的地クラスが共に強要ルーチンを指定するなら、あいまい性はディスパッチの普通のルールによって解決される。 すなわち、$x.Str 常にメソッド形式の方を好むだろうそしてStr($x) 常に関数形式の方を好むだろう。

匿名のクラスの名前が未知であるから、匿名のクラスへの強要がただ目的地クラスによって指定されることができるだけであることに注意を払え:

$someclass = generate_class();
$someclass($x);