For me, the explicit branching solution has the same performance (approximately) as separate methods:
function funvar4!(a, f, V::Vararg{Vector{Float64},N}) where {N}
n = length(V);
for i = 1 : length(a)
if n == 2
a[i] = f(V[1][i], V[2][i]);
else
a[i] = f(V[1][i], V[2][i], V[3][i]);
end
end
end
# With rdeits's inputs:
@btime funvar4!($a, $test, $b, $c);
18.427 μs (0 allocations: 0 bytes)
But I see the drawback of the dynamic dispatch. This is why I thought the dummy solution might be useful (but in the end it runs at the same speed at rdeits’ more elegant solution).
What I don’t understand about rdeits’ solution is why explictly declaring f makes a difference (it doesn’t for my suggestions). My reading is that the method should specialize given that f is used in the body of funvar_new!. Perhaps the catch is in the “should”?