Я пытаюсь добавить методы к функции, похожей на пример функции my_function
ниже. Эти методы следует отправлять при передаче любого из подтипов AbstractWeights
из пакета StatsBase.jl
.
Я не сталкиваюсь с какими-либо проблемами при написании примера функции с типами Abstract и Primitive из пакета Base
. Например.
function my_function(v::Array{<:Real,1})
return sum(v .* 3)/length(v)
end
function my_function(v::Array{<:Real,1}, w::Array{<:Real,1})
return sum(v .* w .* 3)/sum(w)
end
v = [1,2,3]
w = [3,2,1]
my_function(v)
# 6.0
my_function(v, w)
# 5.0
Однако при добавлении методов для типов из StatsBase.jl
я получаю MethodError
ошибки:
using StatsBase
my_function(v::Array{<:Real,1}, w::Array{<:AbstractWeights,1}) = my_function(v,w)
my_function(v::Array{<:Real,1}, w::Array{Weights,1}) = my_function(v,w)
my_function(v, pweights(w))
# ERROR: LoadError: MethodError: no method matching my_function(::Vector{Int64}, ::ProbabilityWeights{Int64, Int64, Vector{Int64}})
my_function(v, weights(w))
# ERROR: LoadError: MethodError: no method matching my_function(::Vector{Int64}, ::Weights{Int64, Int64, Vector{Int64}})
Как я могу написать методы для StatsBase.jl
типов весов выше?
Если функция работала хорошо, должно быть следующее true
my_function(v, w) == my_function(v, weights(w)) == my_function(v, pweights(w)) == my_function(v, fweights(w))
# true
Здесь есть несколько проблем:
AbstractWeights
уже является вектором, поэтому его не нужно оборачивать вектором;Таким образом, вы должны реализовать код:
my_function(v::Vector{<:Real}, w::AbstractWeights) = sum(v .* w .* 3)/sum(w)
sum(v .* w .* 3)/sum(w)
— очень неэффективный способ реализации взвешенной суммы. Он создает ненужный временный массив, а также умножает каждый элемент на 3 вместо простого умножения на 3 в конце. Вместо этого вы можете сделать3 * dot(v, w) / sum(w)
.