2014-04-27 3 views
11

Die Julia style guide sagt der folgende:Julia: Arrays mit abstrakten Parameter führen zu Fehlern aber Variablen mit abstrakten Typen nicht

nicht unnötig statischen Parameter anwenden. Eine Funktion Signatur:

foo{T<:Real}(x::T) = ... 

sollte geschrieben werden als:

foo(x::Real) = ... 

erwartete ich das auch auf Array-Parameter anzuwenden. Allerdings, wenn ich den folgenden Code schreiben:

ret1(x::Real) = x 
ret2(x::Array{Float64,2}) = x 
ret3(x::Array{Real,2}) = x 
ret1(1.0) 
ret2(rand(2,2)) 
ret3(rand(2,2)) 

dann erhalte ich die folgende Ausgabe der Konsole (mit Julia 0.2.1):

MethodError(ret3,(
2x2 Array{Float64,2}: 
0.841121 0.322133 
0.469432 0.495438,)) 

Also warum Julia einen Fehler für Arrays mit abstrakten Typ werfen Parameter, aber nicht für Variablen mit abstrakten Typen?

Antwort

9

Im Falle ret3 ist der Typ-Parameter tatsächlich notwendig, weil ein ein Typ ist, der nie invariant sind Typ-Parameter des Julia aufgebaut werden kann. Dies ist ein bisschen ein subtiles Thema, aber die wichtigste Tatsache ist, dass, während Float64 <: Real ist wahr, Array{Float64} <: Array{Real} ist nicht. Dies ist zunächst etwas verwirrend, aber dies ist notwendig, damit der Compiler das Speicherlayout von Funktionsargumenten bei der Codegenerierung kennen kann. Weitere Informationen hierzu finden Sie unter manual.

So kann man auf einem Real wie in ret1 versenden, denn wenn man es ein Float64 passieren, Float64 <: Real ist wahr, während in ret3 Sie es vorbei ein Array{Float64} und Array{Float64} <: Array{Real} ist nicht der Fall, daher der keine Methode Fehler. Um dies zu beheben, einen Typ-Parameter verwendet werden:

julia> ret3{T <: Real}(x::Array{T,2}) = x 
ret3 (generic function with 2 methods) 

julia> ret3(rand(2,2)) 
2x2 Array{Float64,2}: 
0.0857132 0.353194 
0.802737 0.717292 
+0

Ja, dachte ich, dass die Antwort wäre. Aber dann erfordert es statische Parameter, die sonst unnötig erscheinen würden. Warum hat Julia keinen Array-Typ, der alle Elemente vom selben Typ erzwingt? – user664303

+0

Ich bin etwas verwirrt, Julia eine unendliche Anzahl von Array-Typen, die alle Elemente des gleichen Typs erzwingen: 'Array {Float64}', 'Array {String}', etc. Bedeutet du etwas, das Elemente erzwingt vom selben Typ, ohne zu spezifizieren, was der Typ ist? –

+0

Was ich vorschlage, ist ein Array-Typ wie ArrayHomogenic {T}, wobei T ein abstrakter Typ wie Real oder Number sein kann, für den der Compiler jedoch weiß, dass jedes Element vom selben Typ ist, unabhängig vom Typ. – user664303

2

Im Fall ret3, ein streng Array{Real, 2} erwartet wird, das heißt, eine Anordnung, die jede Art von Real Variablen innerhalb halten kann (während rand(2,2) ist ein Array von Float64 nur).

In diesem Fall wird die statischen Parameter nicht unnötig:

ret3{T<:Real}(x::Array{T,2}) = x