Dies ist ein Versuch, einen Teil der Frage, die ich here gebeten, zu vereinfachen:Wie kann ich eine Eigenschaft in Julia mit offenen Typen schreiben?
Ich möchte einige Code schreiben, der auf Arten arbeiten, die bestimmte Kriterien erfüllen, gewährleistet ist. Lassen Sie uns heute sagen, ich schreibe einige Code:
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)
Lauf dies funktioniert:
julia> x = Example("Hi!")
Example("Hi!")
julia> combine_two_steps(x)
7.5
an einem anderen Tag Dann schreibe ich etwas mehr Code:
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
Und was weißt du, mein generic Mähdrescherfunktion funktioniert immer noch!
julia> y = TotallyDifferentExample(false)
TotallyDifferentExample(false)
julia> combine_two_steps(y)
166.5
Hurra! Aber, sagen wir, es ist eine lange Nacht und ich versuche das WIEDER an einem dritten Beispiel zu machen. Ich erinnere mich daran, step_one
zu implementieren, aber ich vergesse zu implementieren step_two
!
immutable ForgetfulExample
whatever::Float64
end
function step_one(x::ForgetfulExample)
x.whatever+1.0
end
Jetzt, wenn ich dies ausführen, bekomme ich einen Laufzeitfehler!
julia> z = ForgetfulExample(1.0)
ForgetfulExample(1.0)
julia> combine_two_steps(z)
ERROR: MethodError: `step_two` has no method matching step_two(::Float64)
Nun, ich arbeite für einen Manager, der mich töten, wenn ich jemals einen Laufzeitfehler erhalten. Also, was ich tun muss, um mein Leben zu retten, ist, eine Eigenschaft zu schreiben, die im Wesentlichen besagt: "Wenn der Typ diese Eigenschaft implementiert, ist es sicher, combine_two_steps
aufzurufen."
Ich möchte
so etwas wieusing 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 schreiben, dann würde ich wissen, dass wenncombine_two_steps
ist immer geschickt, dann wird laufen, ohne einen Fehler zu erhöhen, dass diese Methoden don Ich existiere nicht.
Äquivalent, istrait(ImplementsBothSteps{X})
(ist wahr) entspricht combine_two_steps
wird ohne Fehler-von-Nichtexistenz-von-erforderlichen-Methoden ausgeführt.
Aber, wie jeder weiß, kann ich diese Merkmaldefinition nicht verwenden, weil Y
keine Bedeutung hat. (In der Tat, seltsam genug, um den Code kompiliert ohne Fehler,
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
aber die Typen erfüllen nicht die Eigenschaft, auch wenn die Methoden für einige Y
existieren.) Mein erster Gedanke ist, ich Y
zu so etwas wie Any
ändern
using Traits
@traitdef ImplementsBothSteps{X} begin
step_one(X) -> Any
step_two(Any) -> Float64
end
aber dies nicht zu b/c der Any
wirklich soll so etwas wie Some
, nicht wörtlich die Any
Typ sein (da ich nie ein Verfahren step_two
implementiert, die jede Art als Eingabe könnte), aber einige besondere Typ, der in beiden Zeilen geteilt wird!
Die Frage ist also: Was würden Sie in dieser Situation tun?Sie möchten eine "Spezifikation" (hier in Form des durch die Eigenschaft ausgedrückten Vertrags) so weitergeben, dass jeder Programmierer, der die Spezifikation erfüllt, garantiert Ihre Funktion combine_two_steps
verwenden kann, aber die Spezifikation hat im Wesentlichen einen Existenzquantifizierer in seiner Definition.
Gibt es eine Problemumgehung? Ein besserer Ansatz zum Schreiben der "Spezifikation" (zB "Traits nicht verwenden, etwas anderes verwenden?") Usw.
Übrigens klingt es vielleicht künstlich, aber die oben verlinkte Frage und diese Frage kommen regelmäßig in einem Projekt, an dem ich gerade arbeite. Ich bin im Wesentlichen an einer Straßensperre fest, die durch dieses Problem verursacht wird, und habe hässliche Problemumgehungen, die von Fall zu Fall funktionieren, aber keine Annäherung an den allgemeinen Fall.
Können Sie bitte die Details veröffentlichen. –