ジュリアにおける機能署名と派遣行動の明確化


8

ジュリア(1.2)REPLでいくつかのことを試していましたが、ディスパッチについてわからないことを思いつきました。


私は最初に私が期待した方法で機能しているこのことを試しました:

f(a::T) where {T <: Int} = "Test"

  • f(3)の呼び出しは、 Int <: Int == true

  • f( "Hello")を呼び出すと、「MethodError:no method matching」エラーが発生します。 String <: Int == false


次に、私はこのメソッドを試しましたが、なぜそれを呼び出すことがいくつかのケースで機能するのかわかりません:

f(a::T, b::U) where {T, U <: T} = "Another Test"

  • f(3、3)を呼び出すと(期待どおり)機能します

  • しかしf(3、 "Hello")も機能し、「MethodError:no method matching」をスローしません???

私はそれを考えました(TがIntになり、Uが文字列になるため)String <: Int == false???


ここにはかなり簡単なものが欠けていると思いますが、見つかりません...これが私の質問です。なぜf(3、 "Hello")が機能しているのですか?


さらに、私はこのコードスニペット(2番目のメソッドシグネチャを再作成しようとしました)を試しましたが、期待どおりに正しく失敗しました。

Test = Tuple{T, U} where {T, U <: T}

Test{Int, String} (これは、「TypeError:タイプで、Uで、予期されたU <:Int64、タイプ{文字列}を取得した」で期待どおりに失敗します)


1
f()が返す最後の定義を再現できませんInt64,String,false。関数にメソッドを追加する場合、Juliaを再起動する必要があるかもしれません。新しい文字を使用するだけで、たとえばh新しいテストに使用できます。あなたの質問に:システムを見つけようとすることが表示されます任意のタイプの制限に対する解決策を、そしてT=Any, U=Any where U:<T一つです。3番目の例のように具象型を導入すると、期待どおりに機能します。より正確なジュリア型システムの知識を持つ人々は、これに対してすぐに適切な答えを出すでしょう。
1

ああ!そうです、Juliaを再起動する必要がありました... T <を使用した再定義:Intは、最後のTのみ(警告なし...)をオーバーライドしませんでした。そして、TとUのソリューションとしてAnyを見つけるシステムについてのあなたの答えは、すべてを説明します!ありがとうございます:)
SnoopyDoowop

回答:


4

ここで何が起こっているかというと、それTはデータ型でありU、文字列の任意のスーパータイプである可能性があります。この条件が満たされています。文字列がintのサブタイプではないことであなたをつまずかせていたのは、具体的なタイプが他のサブタイプではないため、レッドニシンです。


そしてなぜタプル定義ではなくエラーが発生するのですか?
アントネッロ

3

労働のおかげで、何が起こっているのか理解できたようです。この方法を取る場合:

f(a::T, b::U) where {T, U <: T} = "Another Test"

  • 「T」は、可能なすべてのタイプの「a」の「UnionAll」または「反復型ユニオン」です。
  • 「U」は、「T」のサブタイプである「b」のすべての可能なタイプの「UnionAll」または「反復型ユニオン」です

  • (例)a :: Intの場合、Tがtypeof(a)の親の抽象型を取ることができるという事実を誤解していました。Int <:Anyなので、T = Anyがディスパッチの有効なソリューションです。

  • 文字列<:Anyなので、U = Anyでも同じです。

これで、U <:TがAny <:Any == trueに解決され、メソッドが呼び出されました。

私はそれを得ることを望みます:)


あなたがやる。この時点で、あなたのものは私のものよりも良い答えです。
オスカースミス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.