Si tratta di un tentativo di semplificare una parte della questione ho chiesto here:Come posso scrivere un tratto in Julia con tipi aperti?
voglio scrivere del codice che è garantito per lavorare sui tipi che soddisfano determinati criteri. Diciamo che oggi ho scrivere del codice:
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)
L'esecuzione di questo funziona:
julia> x = Example("Hi!")
Example("Hi!")
julia> combine_two_steps(x)
7.5
Poi un altro giorno ho scrivere del codice più:
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
E che ne sai, la mia generica la funzione combinata funziona ancora!
julia> y = TotallyDifferentExample(false)
TotallyDifferentExample(false)
julia> combine_two_steps(y)
166.5
Evviva! Ma, diciamo che è una notte tarda e sto cercando di farlo di nuovo su un terzo esempio. Mi ricordo di implementare step_one
, ma ho dimenticato di implementare step_two
!
immutable ForgetfulExample
whatever::Float64
end
function step_one(x::ForgetfulExample)
x.whatever+1.0
end
Ora, quando eseguo questo, otterrò un errore in fase di esecuzione!
julia> z = ForgetfulExample(1.0)
ForgetfulExample(1.0)
julia> combine_two_steps(z)
ERROR: MethodError: `step_two` has no method matching step_two(::Float64)
Ora, io lavoro per un manager che ucciderà me se mai avrò un errore di run-time. Quindi quello che devo fare per salvarmi è scrivere un Tratto che dice essenzialmente "se il tipo implementa questa caratteristica, allora è sicuro chiamare combine_two_steps
".
voglio scrivere qualcosa di simile
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 allora io so che se combine_two_steps
è mai spedito, allora sarà corsa senza sollevare un errore che questi metodi don esiste
Equivalentemente, istrait(ImplementsBothSteps{X})
(essere vero) è equivalente a combine_two_steps
verrà eseguito senza errori da non-inesistenza-di-requisiti-metodi.
Ma, come tutti sanno, non posso usare quella definizione di tratto, perché Y
non ha significato. (In realtà, stranamente il codice viene compilato senza errori,
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
ma i tipi non soddisfano la caratteristica, anche se esistono metodi per qualche Y
.) Il mio primo pensiero è che posso cambiare Y
a qualcosa come Any
using Traits
@traitdef ImplementsBothSteps{X} begin
step_one(X) -> Any
step_two(Any) -> Float64
end
ma questo non troppo b/c il Any
davvero si suppone che sia qualcosa di simile Some
, non letteralmente il tipo Any
(dal momento che non ho mai implementato un metodo step_two
che potrebbe assumere qualsiasi tipo di ingresso), ma qualche particolaredigita condiviso su entrambe le righe!
Quindi, la domanda è: cosa faresti in questa situazione?Si vuole passare attorno a una "specifica" (qui nella forma del contratto espressa dal Tratto) in modo tale che qualsiasi programmatore che soddisfi le specifiche sia garantito per poter utilizzare la propria funzione combine_two_steps
, ma la specifica ha essenzialmente un quantificatore esistenziale nella sua definizione.
C'è una soluzione? Un approccio migliore alla scrittura delle "specifiche" (es. "Non usare i tratti, usa qualcos'altro"?) Etc.
A proposito, può sembrare forzato, ma la domanda di cui sopra e questa domanda stanno arrivando regolarmente su un progetto a cui sto lavorando. Sono essenzialmente bloccato a un posto di blocco causato da questo problema e ho brutte soluzioni alternative che funzionano caso per caso, ma nessun approccio al caso generale.
Potete per favore pubblicare i dettagli. –