dynamic Vararg count

The following code fails to compile (if n is not defined in Main that is). Is there a way to do something like this?

function f(n::Int); g(x::Vararg{Float64,n}) = sum(x); end

If you want a version of sum that accepts any number of arguments try

Base.sum(xs...) = sum(xs)

Probably shouldn’t make it a method of Base.sum though (type piracy).

1 Like

I agree.

sum_of(xs...) = sum(xs)

Strange question, I’m not sure I understand. You want to define g so that it only accepts a Vararg with exactly n elements, and give a MethodError otherwise? If that is what you indeed need, I guess I would suggest looking into @generated functions. If you don’t “need” to throw a MethodError but rather just sum n arguments (if available), why don’t you just do the following?

function f(n::Int)
    g(xs...) = sum(xs[1:n])
   # rest of code
end

“sum” is a simplified example. I’m really not looking to replace sum. The real problem is that I want to write a generic maximum likelihood heuristic optimizer for arbitrary distributions. JuMP requires arguments passed as scalars. The question is whether one can dynamically define Varargs.

Yes. I’m trying to define the method to have as precise a signature as possible. Loosening the signature is probably what I’ll do for now. I’ll look into @generated functions. Thanks for suggesting it. I saw something about this for the first time the other day but am not yet familiar with it.

You don’t want the method signature to depend on a runtime argument like n since that would force it to be recompiled every time you call your function f with a new argument value. Recompilation is slow — except in special cases, you typically only want to recompile when the argument types change, not the values.

Is the following precise enough?

julia>  f(xs::Float64...) = print("type: ", typeof(xs), ", length: ", length(xs))
julia> f(1.0,2.4)
type: Tuple{Float64,Float64}, length: 2

or

julia> g(xs::T...) where T = print("type: ", typeof(xs), ", length: ", length(xs))
julia> g(1,2,3)
type: Tuple{Int64,Int64,Int64}, length: 3

f doesn’t get called often. In the real example, it will get called and then passes g into a function which will likely call it many thousands of time.

Thanks. That’s close to what I’m looking for. I’m using that for now. It still doesn’t restrict subsequent callers from using the wrong number of Float64’s (which will ultimately fail but I’d rather catch it earlier). Anyway, thanks.