これは私がhereを尋ねた質問の一部を簡素化する試みです。のは、私はいくつかのコードを書き、今日言ってみましょう:どのようにしてJuliaでOpen-ended型のTraitを書くことができますか?</p> <p>私は一定の基準を満たすタイプの上で動作することが保証されていくつかのコードを書きたい:
immutable Example
whatever::ASCIIString
end
function step_one(x::Example)
length(x.whatever)
end
function step_two(x::Int64)
(x * 2.5)::Float64
end
function combine_two_steps{X}(x::X)
middle = step_one(x)
result = step_two(middle)
result
end
x = Example("Hi!")
combine_two_steps(x)
は、この作品の実行:
immutable TotallyDifferentExample
whatever::Bool
end
function step_one(x::TotallyDifferentExample)
if x.whatever
"Hurray"
else
"Boo"
end
end
function step_two(x::ASCIIString)
(Int64(Char(x[end])) * 1.5)::Float64
end
そして、あなたが知っている、私のジェネリック:
julia> x = Example("Hi!")
Example("Hi!")
julia> combine_two_steps(x)
7.5
はその後、別の日、私はいくつかのより多くのコードを書きます機能を組み合わせる機能はまだあります!
julia> y = TotallyDifferentExample(false)
TotallyDifferentExample(false)
julia> combine_two_steps(y)
166.5
ハレイ!しかし、それは深夜で、私はもう一度これを第3の例でやろうとしています。私はstep_one
を実装することを忘れないでくださいが、私はstep_two
を実装することを忘れています!
immutable ForgetfulExample
whatever::Float64
end
function step_one(x::ForgetfulExample)
x.whatever+1.0
end
これを実行すると、実行時エラーが発生します。
julia> z = ForgetfulExample(1.0)
ForgetfulExample(1.0)
julia> combine_two_steps(z)
ERROR: MethodError: `step_two` has no method matching step_two(::Float64)
私は今まで実行時エラーが発生した場合、私を殺してくれるマネージャーのために働いています。だから、私の人生を救うために必要なことは、「この種の型がこの種の形質を実装すれば、combine_two_steps
に電話をかけることは安全です」と言う本質的な特徴を書くことです。
は、私はその後、私はがを派遣場合combine_two_steps
が今までであることを知っているだろう
using Traits
@traitdef ImplementsBothSteps{X} begin
step_one(X) -> Y
step_two(Y) -> Float64
end
function combine_two_steps{X;ImplementsBothSteps{X}}(x::X)
middle = step_one(x)
result = step_two(middle)
result
end
B/Cのようなものを書きたいこと意志エラーを出さずに実行することを、これらのメソッドドン存在しない。
これに相当すると、istrait(ImplementsBothSteps{X})
(真)は、エラーが発生しないエラーのない方法で実行されるcombine_two_steps
に相当します。
しかし、誰もが知っているようY
は意味を持ちませんので、私は、その特性の定義を使用することはできません。 (実際には、奇妙なコードは、エラーなしでコンパイル
julia> @traitdef ImplementsBothSteps{X} begin
step_one(X) -> Y
step_two(Y) -> Float64
end
julia> immutable Example
whatever::ASCIIString
end
julia> function step_one(x::Example)
length(x.whatever)::Int64
end
step_one (generic function with 1 method)
julia> function step_two(x::Int64)
(x * 2.5)::Float64
end
step_two (generic function with 1 method)
julia> istrait(ImplementsBothSteps{Example})
false
が、種類は方法がいくつかY
のために存在していても形質を満たしていない。)私が最初に考えたのは、私がAny
のようなものにY
を変更することができますです
using Traits
@traitdef ImplementsBothSteps{X} begin
step_one(X) -> Any
step_two(Any) -> Float64
end
が、これは、B/C Any
は本当にSome
、ない文字通りAny
タイプ(私は、入力として任意の型を取ることができる方法step_two
を実施したことがないので)のようなものになるはずが、いくつかは、特定されすぎて失敗します両方の行で共有されるタイプです。
だから、質問です:あなたはこのような状況で何をしますか?仕様を満たすプログラマーがあなたの関数combine_two_steps
を使用できることが保証されているように、スペック(ここではTraitのコントラクトの形で)を渡したいが、スペックは本質的に存在量限定子その定義において。
回避策はありますか? 「仕様を書いて、他のものを使用しない」などの「スペック」を書く方が良いでしょう。
ところで、上記の質問とこの質問は来ているかもしれません私が取り組んでいるプロジェクトでは定期的に活動しています。私は本質的にこの問題によって引き起こされたロードブロッキングに悩まされており、ケースバイケースでは動作しない醜い回避策を持っていますが、一般的なケースではアプローチはありません。
詳細を投稿できますか? –