Function wrapper for custom functions

Hi everyone,

I have 2 functions defined that are used for resampling a vector of reals:

using Distributions
using BenchmarkTools

function resampling_multinomial(weights::AbstractVector{T}, particlesN::Int) where {T<:Real}
rand(Categorical(weights), particlesN )
end

function resampling_systematic(weights::AbstractVector{T}, particlesN::Int) where {T<:Real}
#Assign cumulative Weights
uniforms = rand.( Uniform.(0, 1/particlesN) ) .+ range(0; step = 1/particlesN, length = particlesN)
path       = zeros(Int, particlesN, 1)
#Some other calculations
return path
end

resampling_multinomial( [.1, .2, .3, .4], 100) #Int64[100]
resampling_systematic( [.1, .2, .3, .4], 100) # 100*1 Array{...}

Now I would like to define a wrapper function with a more suitable name and call either of the function based on a stringname from the arguments.

#Wrapper function for my custom functions
resample(weights::AbstractVector{T}, particlesN::Int, method::String = "multinomial") where {T<:Real} = resampling_multinomial(weights, particlesN)
resample(weights::AbstractVector{T}, particlesN::Int, method::String = "systematic") where {T<:Real} = resampling_systematic(weights, particlesN)
#Default method
resample(weights, particlesN) = resample(weights, particlesN; method = "systematic")

#NOT working
resample( [.1, .2, .3, .4], 100, "multinomial") # NOT CORRECT - 100*1 Array instead of Int64[100]
resample( [.1, .2, .3, .4], 100, "systematic") # 100*1 Array
resample( [.1, .2, .3, .4], 100) # 100*1 Array

Unfortunately, this is not working. I cannot dispatch the functions cause the two functions do not differentiate in any type. If I try it the way I did above the function wrapper just gets overwritten and will always use the last line of code.
QUESTION: How can I define a more convenient function name and call either of my custom resampling functions based on a stringname from the arguments?

Best regards,

Why not a simple branch:

function resample(weights, particlesN; method = "systematic")
  if method == "systematic"
    resampling_systematic(...)
  else
    resampling_multinomial(...)
end

I suppose if you really wanted to dispatch at compile time you could define struct Systematic end and struct Multinomial end and define wrappers of the form

function resample(weights, particlesN, method :: Systematic)
  resampling_systematic(...)
end
1 Like

Thank you! I think the second suggestion is the way to go for me. I did not really want to branch it as these functions will be called many times in other functions.

Iā€™m just wondering: can the compiler infer the type of method while the programmer cannot?

I would check @code_warntype on this code if performance is important.

It seems to be able to, @code_warntype gives the following output for the problem above:

Body::Array{Int64,2}
1 ā”€ %1 = invoke Main.resampling_systematic(_2::Array{Float64,1}, _3::Int64)::Array{Int64,2}
ā””ā”€ā”€      return %1

I still need to call Multinomial() and Systematic() instead of Multinomial and Systematic in the function wrapper as the latter are no structs but apart from that it is perfect.

I was suggesting to make up structs that work rather like an enum. That is, define

struct Systematic end

so that you can dispatch on the function signature by passing an object of type Systematic.

Perhaps I misunderstood your reply, though.