2017-06-19 5 views
4

引数リストに配列を作成するこのプログラムを考えてみましょう。配列を受け取り、署名がありますが、これはリストを受け入れるものを呼び出します。Perl 6のマルチディスパッチはどのルーチンを使用するかをどのように決めるのですか?

foo([ 1, 2, 3 ]); 

multi foo (Array @array) { put "Called Array @ version" } 
multi foo (Array $array) { put "Called Array \$ version" } 
multi foo (List $list) { put "Called List version" } 
multi foo (Range $range) { put "Called Range version" } 

私は予想外のルーチンからの出力を得る:私は、そのいずれかを、他の署名のコメントを解除した場合

Called Array $ version 

Called List version 

なぜ(Array @array)バージョンを呼び出さないのですか?ディスパッチャーはどのように決定しますか(そしてそれはどこに文書化されていますか)。

+1

cf 'say( - > Array @ {})。signature.params [0]。タイプ ' – Christoph

+0

@briandfoy私はノイズの低減のために逆転に関する私のコメントを削除しました。あなたの確認のコメントも削除してください。後で私はこれを削除します。 :) – raiph

+0

briandfoyあなたは答えを受け入れていません。私はもっ​​と頑張ります。私は完全に "なぜそれが呼び出されないのか..."と言いました。私は、「ディスパッチャーはどのように決定を下していますか?それはあなたの特定の例に関連しているからです。私は@ Sladeの答えがより広くそれに対処したと思う。しかし、あなたは「これは私が示した行動を説明するものではありません」と書いています。彼らの答えに対する私のコメントによると、私はそれがそうだと思います。私は自分の答えを「どこに文書化されていますか? Sladeの答えに対応するdocにリンクしてください。私はあなたの指導に感謝します。 :) – raiph

答えて

1

私は本当にダムの間違いを犯しました。それが私が私が期待していたものを見ていない理由です。 @で始まる変数を制約することはできません。制約はその要素に適用されます。 Array @arrayは、私が各要素がArrayであるようなポジションを持っていることを示しています。これはthe same thing that raiph saidです。奇妙なことは、文法は同じに見えますが、それは異なることです。それは私が以前に乗り越えたものです。

、それは別の何かをやっているので、データ構造が一致していても動作するようにつもりはない:

foo([ [1], [2], [3] ]); 
foo([ 1, 2, 3 ]); 

multi foo (Array @array) { put "Called Array @ version" } 
multi foo (Array $array) { put "Called Array \$ version" } 
multi foo (List $list) { put "Called List version" } 
multi foo (Range $range) { put "Called Range version" } 

私はまだ私が制約とデータ構造に基づいて期待していないバージョンを取得します

Called Array $ version 
Called Array $ version 

これは、通常のユーザーが学ばなければならないPerl 6の疣贅の1つになると思います。

5

なぜ(Array @ array)バージョンを呼び出さないのですか?

あなたのテストfooコールは、引数、ないArray S(例えば[[1,2,3],[4,5,6]])の配列としてだけアレイ([1,2,3])を持っています。

@array@does Positional、例えばアレイまたはリストした値を示している。Array @arrayは同じことを示しているが、その配列、リストまたは何Arrayでの各要素の追加の制約を有する。)

ディスパッチャはどのように決定していますか?

それが最も狭いマッチタイプを選んだ、単純化:(。Diagram of subtype relationships of Array, List and Positional

multi foo (Array  )    {} # Narrowest 
multi foo (List  )    {} # Broader 
multi foo (Positional )    {} # Broader still 
multi foo (@array  )    {} # Same as `Positional` 

詳細の多くがjnthn's authoritative answer to a related SO questionを参照してください

(そしてそれはどこに文書化されていますか?)

私はドキュメントについてよくわかりません。 Multi-dispatchはかなり小さく見えます。

-1

デザインドキュメント(完全ではあるが古くなったもの)とドキュメント(不完全であることが知られていますが、docs.perl6.orgが認識していますが、うまくいけば最新のもの)との間にトレードオフがあるようです。前者はSynopsis 12のマルチサブ解像度を説明しています。抜粋:

特定の短い名前のルーチンを呼び出すと、複数の表示可能な長い名前がある場合、すべてが候補とみなされます。引数の実行時の型が各候補のパラメータの宣言された型とどのくらい近いかに応じて、それらは順序にソートされます。ネクタイがない限り、最善の候補が呼び出されます。この場合、タイされた候補は、追加のタイブレーカー戦略(下記参照)を使用して再配布されます。 [...]

3つのタイブレイクモードが絶望の昇順に、ある:

A)は内部または派生範囲

B)実行時制約処理

C)でマークされた候補者の使用"デフォルトです"

Tiebreaker Aは、外側またはより派生していない範囲内の候補に対して内側またはより派生した範囲内の候補を単純に優先します。同じスコープの候補については、タイブブレーカーBに進みます。

制約がない場合、タイブレーカーAのタイはすぐにタイブレーカーCにフェールオーバーします。 Cによって解決されなければ、コンパイル時にあいまいなディスパッチについて警告します。 [...]

正確性について証言するにはPerl 6について十分に分かりませんが、それはraith’s answerと一致しているようですが、追加の説明もあります。

+0

これは私が示した動作を説明していません。 –

+1

@briandfoy Imo最初の部分は、あなたが示した動作をカバーしています:「特定の短い名前のルーチンを呼び出すとき、複数の表示可能な長い名前がある場合、それらはすべて候補とみなされます。引数の実行時の型は、各候補のパラメータの宣言された型と一致します。タイがない限り、最良の候補が呼び出されます... "最も類似した型の候補が勝つように同値はありません。 – raiph

2

「コンテナ」についてです。私は完全な規則をもたらすことはできませんが、いくつかの例を示すことができます。我々はいくつかの変更を加えた場合、明示的にコンテナmy @array

my Array @array = [ [1], [2], [3] ]; 

foo(@array); 

multi foo (Array @array) { put "Called Array @ version" } 
multi foo (Array $array) { put "Called Array \$ version" } 

# Ambiguous call to 'foo'; these signatures all match: 
# :(Array @array) 
# :(Array $array) 

を構築して

は:

my @array = [ 1, 2, 3 ]; 

foo(@array); 

multi foo (@array) { put "Called Array @ version" } 
multi foo (Array $array) { put "Called Array \$ version" } 

# Called Array $ version 

Array $arrayが狭すぎるようです。 my @array = [1, 2, 3],@arrayPositionalである。

foo([ 1, 2, 3 ]); 

multi foo (@array) { put "Called Array @ version" } 
multi foo ($array) { put "Called Array \$ version" } 

# Called Array @ version 

foo([ 1, 2, 3 ]); 

multi foo ($array) { put "Called Array \$ version" } 

# Called Array $ version 

Array $arrayそれはより(何とかより「狭い」配列であることを意味している間に戻る第1の実施例と、Array @arrayは、パラメータのタイプが制約アレイとの位置のものであることを意味ポジション)、結果としてまだネクタイ。

関連する問題