2015-11-06 3 views
6

Sono un po 'confuso circa le annotazioni di tipo nel costruttore interno di tipo parametrico.Costruttore interno di tipo parametrico

Ci sono differenze nei seguenti 4 approcci, in termini di efficienza dell'inferenza JIT e efficienza di runtime?

immutable MyType{T} 
    x::T 
    MyType{T}(x::T) = new{T}(x + x) 
end 

immutable MyType{T} 
    x::T 
    MyType(x::T) = new{T}(x + x) 
end 

immutable MyType{T} 
    x::T 
    MyType(x::T) = new(x + x) 
end 

immutable MyType{T} 
    x::T 
    MyType{T}(x::T) = new(x + x) 
end 

Tutti lavorano per x = MyType{Int}(1)

risposta

2

modo "canonica" per definire un costruttore interna di tipo parametrico è:

immutable MyType{T<:"specific abstract type"} 
    x::T 
    MyType(x) = new(x + x) 
end 

invece di dichiarare la funzione generale MyType(x) che può accettare arbitrario valori, julia ha definito automaticamente molti specifici MyType(x::T) s dove T<:"specific abstract type". quindi i tuoi ultimi due esempi sono equivalenti a questo.

come sappiamo, la funzionalità di new consiste nel creare nuovi oggetti, non è necessario renderlo parametrico, perché abbiamo già applicato i vincoli prima di chiamare questa funzione.

Cordiali saluti, il costruttore di default è diverso da quelli di cui sopra:

immutable MyType{T<:"specific abstract type"} 
    x::T 
end 

qui, Julia si fa una cosa: definire un costruttore esterno:

MyType{T<:"specific abstract type"}(x::T) = MyType{T}(x)

julia> methods(MyType) 
3-element Array{Any,1}: 
call{T<:Integer}(::Type{MyType{T<:Integer}}, x::T<:Integer) at none:2 
call{T}(::Type{T}, arg) at essentials.jl:56       
call{T}(::Type{T}, args...) at essentials.jl:57 

ma:

julia> immutable MyType{T<:Integer} 
      x::T 
      MyType(x) = new(x) 
     end 

julia> methods(MyType) 
2-element Array{Any,1}: 
call{T}(::Type{T}, arg) at essentials.jl:56  
call{T}(::Type{T}, args...) at essentials.jl:57 

ciò significa che potrebbe essere necessario definire manualmente tale costruttore esterno, se si desidera un costruttore interno personalizzato.

1

dichiarai MyType utilizzando i suddetti 4 approcci:

immutable MyType1{T} 
    x::T 
    MyType1{T}(x::T) = new{T}(x + x) 
end 
immutable MyType2{T} 
    x::T 
    MyType2(x::T) = new{T}(x + x) 
end 
immutable MyType3{T} 
    x::T 
    MyType3{T}(x::T) = new(x + x) 
end 
immutable MyType4{T} 
    x::T 
    MyType4(x::T) = new(x + x) 
end 

poi stampate loro bytecode LLVM: code_llvm(MyType1{Int},Int) e confrontato le uscite, sono esattamente la stessa cosa, quindi penso che non ci sono differenze tra i 4 approcci.