Джулия: массивы с абстрактными параметрами вызывают ошибки, а переменные с абстрактными типами-нет.
Руководство по стилю Julia гласит следующее:
Не используйте ненужные статические параметры. Сигнатура функции:
foo{T<:Real}(x::T) = ...
Следует записать как:
foo(x::Real) = ...
Я ожидал, что это относится и к параметрам массива. Однако, если я напишу следующий код:
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))
Затем я получаю следующий консольный вывод (используя Julia 0.2.1):
MethodError(ret3,(
2x2 Array{Float64,2}:
0.841121 0.322133
0.469432 0.495438,))
Так почему же Джулия выдает ошибку для массивов с параметрами абстрактного типа, но не для переменных с абстрактными типами?
2 ответа:
В случае
ret3
параметр типа фактически необходим, потому чтоanпараметры типа Джулии инвариантны. Это немного тонкая тема, но ключевой факт заключается в том, что, хотяArray{Real}
- это тип, который никогда не может быть построенFloat64 <: Real
истинно,Array{Float64} <: Array{Real}
является не. Сначала это немного сбивает с толку, но это необходимо для компилятора, чтобы иметь возможность знать расположение аргументов функции в памяти при создании кода. Дополнительную информацию смотрите в руководстве . этот.Таким образом, вы можете отправить на
Real
как вret1
, потому что когда вы передаете его aFloat64
,Float64 <: Real
верно, тогда как вret3
Вы передаете егоArray{Float64}
, аArray{Float64} <: Array{Real}
не имеет места, следовательно, ошибка метода no. Чтобы исправить это, используйте параметр типа: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