Я новичок в Julia, и, учитывая мое происхождение Matlab, у меня возникли трудности с определением того, как написать "хороший" код Юлии, который использует преимущества множественной отправки и системы типа Julia.
Рассмотрим случай, когда у меня есть функция, которая предоставляет квадрат a Float64
. Я мог бы написать это как:
function mysquare(x::Float64)
return(x^2);
end
Иногда я хочу скомпоновать все Float64
в одномерном массиве, но не хочу каждый раз выписывать цикл через mysquare
, поэтому я использую множественную отправку и добавляю следующее:
function mysquare(x::Array{Float64, 1})
y = Array(Float64, length(x));
for k = 1:length(x)
y[k] = x[k]^2;
end
return(y);
end
Но теперь я иногда работаю с Int64
, поэтому я пишу еще две функции, которые используют множественную отправку:
function mysquare(x::Int64)
return(x^2);
end
function mysquare(x::Array{Int64, 1})
y = Array(Float64, length(x));
for k = 1:length(x)
y[k] = x[k]^2;
end
return(y);
end
Правильно ли это? Или существует более идеотический способ справиться с этой ситуацией? Должен ли я использовать параметры типа, подобные этому?
function mysquare{T<:Number}(x::T)
return(x^2);
end
function mysquare{T<:Number}(x::Array{T, 1})
y = Array(Float64, length(x));
for k = 1:length(x)
y[k] = x[k]^2;
end
return(y);
end
Это кажется разумным, но будет ли мой код работать так же быстро, как в случае, когда я избегаю параметрических типов?
Итак, на мой вопрос две части:
-
Если мне нужен быстрый код, следует ли использовать параметрические типы, как описано выше, или написать несколько версий для разных конкретных типов? Или я должен делать что-то еще?
-
Когда мне нужна функция, которая работает как с массивами, так и с скалярами, полезно ли писать две версии функции: одну для скаляра и одну для массива? Или я должен делать что-то еще?
Наконец, пожалуйста, укажите любые другие проблемы, о которых вы можете думать в коде выше, поскольку моей конечной целью здесь является написать хороший код Юлии.
OP UPDATE: Обратите внимание, что в последней версии Julia (v0.5) идиоматический подход к ответу на этот вопрос состоит в том, чтобы просто определить mysquare(x::Number) = x^2
. Этот векторизованный случай покрывается с использованием автоматического широковещания, т.е. x = randn(5) ; mysquare.(x)