Как я могу указать тип для аргумента функции, не ограничивая его размеры?

В Julia я хочу указать тип аргумента функции в виде массива массивов. Так что я

function foo{T <: Any}(x::Array{Array{T}})

но если я поставлю аргумент x в REPL, например:

x = Array[[0,1],[1,2,3],[0,1,2,4]]

затем он автоматически получает следующее назначение типа (например), которое включает его размеры:

x::Array{Array{T,N},1}

так что я получаю ошибку

ERROR: `foo` has no method matching foo(::Array{Array{T,N},1}).

Я не хочу вообще ограничивать размеры массива, поэтому думал, что решение может быть чем-то вроде

function foo{T <: Any, N <: Number}(x::Array{Array{T,N},N})

но это тоже не работает.

Как я могу указать тип аргумента, чтобы быть массивом массивов?

1 ответ

Решение

Дан массив массивов x = Array[isodd(i) ? [1i,2i] : [1.0i 2.0i] for i=1:10]Юлия сообщает свой тип как Array{Array{T,N},1}, Это обманчиво, так как кажется, что существует T и немного N для которого вышеуказанный тип будет соответствовать. Но это не так: нечетные элементы будут иметь тип Array{Int,1}и вечера Array{Float64,2}, Поэтому, когда вы пытаетесь написать метод для foo с параметрами типа:

foo{T,N}(::Array{Array{T,N},1}) = T,N

Что T а также N за x? Понятно, что такого N нет - это и 1, и 2! И элементы этих подмассивов не имеют типа Any - они оба Int а также Float64, То же самое относится и к Array[[0,1],[0,1,2]]хотя в вашем примере вы знаете, что T а также N непротиворечивы, система типов Джулии не... и вы могли бы потенциально выдвигать элементы, которые не являются векторами Int.

Есть немало способов обойти это. Наилучший подход состоит в том, чтобы убедиться, что ваши массивы всегда имеют конкретные (или хотя бы одинаковые) типы элементов, но это не всегда возможно. Учитывая ваш пример x выше, вы могли бы вместо этого написать: x = Array{Int,1}[[0,1],[1,2,3],[0,1,2,4]],

Другой вариант - изменить сигнатуру вашей функции:

foo{N}(x::Array{Array,N}) = 1 # Will *only* work for arrays like x above
foo{T<:Array, N}(x::Array{T,N} = 2 # Will work for all arrays of arrays

Первый будет применяться только в том случае, если у вас точно такой тип из-за неизменности, тогда как второй будет работать для всех массивов массивов, как плохо набранных, так и конкретных.

(Изменить: В качестве заключительной записки, N<:Number не будет соответствовать буквальным числам. Это будет соответствовать типам, которые являются подтипом Number, лайк Real или же Int, В настоящее время нет способа выразить, что параметр типа должен быть значением типа Int вне соглашения, что N является целым числом).

Другие вопросы по тегам