関数定義で関数パラメーターのサブタイプを使用したいと思います。これは可能ですか?たとえば、次のように書きたいと思います。
g{T1, T2<:T1}(x::T1, y::T2) = x + y
したがって、それはのサブタイプであるすべてに対してg
定義されます。明らかに、たとえば、それが常にであることがわかっていれば、私は書くことができ、これはうまくいくでしょう。ただし、この質問は、実行時までわからない場合に使用します。x::T1
y
T1
T1
Number
g{T<:Number}(x::Number, y::T) = x + y
T1
なぜ私がこれをやりたいのか疑問に思っているなら、読んでください:
私がやろうとしていることの完全な説明は少し面倒ですが、以下は単純化された例です。
パラメータ化されたタイプと、そのタイプに対して定義された単純なメソッドがあります。
type MyVectorType{T}
x::Vector{T}
end
f1!{T}(m::MyVectorType{T}, xNew::T) = (m.x[1] = xNew)
次のように定義された抽象的なスーパータイプを持つ別のタイプもあります
abstract MyAbstract
type MyType <: MyAbstract ; end
次を使用するようにMyVectorType
設定されたベクトル要素タイプのインスタンスを作成しますMyAbstract
。
m1 = MyVectorType(Array(MyAbstract, 1))
のインスタンスをMyType
に配置したいと思いますMyVectorType
。以来、私はこれを行うことができますMyType <: MyAbstract
。ただし、f1!
関数定義はxNew
、型T
である必要があり、ではなく、にT
なることを意味するため、これを行うことはできませMyAbstract
んMyType
。
この問題に対して私が考えることができる2つの解決策は次のとおりです。
f2!(m::MyVectorType, xNew) = (m.x[1] = xNew)
f3!{T1, T2}(m::MyVectorType{T1}, xNew::T2) = T2 <: T1 ? (m.x[1] = xNew) : error("Oh dear!")
1つ目は、基本的にダックタイピングソリューションです。2番目は、最初のステップで適切なエラーチェックを実行します。
どちらが好ましいですか?それとも、私が気付いていない3番目のより良い解決策はありますか?
関数を定義する機能g{T, S<:T}(::Vector{T}, ::S)
は、対角ディスパッチのアナロジーとして「三角ディスパッチ」と呼ばれていますf{T}(::Vector{T}, ::T)
。(スーパータイプが上と左になるように配置された、行と列にラベルを付けるタイプ階層を持つテーブルを想像してください。行は最初の引数の要素タイプを表し、列は2番目の引数のタイプを表します。斜めのディスパッチはテーブルの対角線に沿ったセルのみに一致しますが、三角形ディスパッチは対角線とその下のすべてに一致し、三角形を形成します。)
これは単にまだ実装されていません 。これは複雑な問題です。特に、関数定義の範囲内T
と範囲S
外、および不変性のコンテキストで検討を開始すると、問題になります。詳細については、問題#3766および#6984を参照してください。
したがって、実際には、この場合、ダックタイピングは問題ないと思います。の実装に依存して、myVectorType
要素を割り当てるときにエラーチェックを実行します。これは、どのような場合でも実行する必要があります。
配列の要素を設定するためのベースジュリアのソリューションは次のようなものです。
f!{T}(A::Vector{T}, x::T) = (A[1] = x)
f!{T}(A::Vector{T}, x) = f!(A, convert(T, x))
タイプ階層やサブタイプ「三角形」については気にしないことに注意してください。それだけで変換しようとx
するT
...場合は何もしませんいますx::S, S<:T
。またconvert
、変換できない場合や方法がわからない場合はエラーが発生します。
更新:これは最新の開発バージョン(0.6-dev)に実装されました!この場合でもconvert
、最初に答えたように使用することをお勧めしますが、静的メソッドパラメーター内で左から右の方法で制限を定義できるようになりました。
julia> f!{T1, T2<:T1}(A::Vector{T1}, x::T2) = "success!"
julia> f!(Any[1,2,3], 4.)
"success!"
julia> f!(Integer[1,2,3], 4.)
ERROR: MethodError: no method matching f!(::Array{Integer,1}, ::Float64)
Closest candidates are:
f!{T1,T2<:T1}(::Array{T1,1}, ::T2<:T1) at REPL[1]:1
julia> f!([1.,2.,3.], 4.)
"success!"
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加