Whoops, sorry, I missed that
In that case, this seems like a great time for some metaprogramming! How does this look?
julia> @generated function outer(f, args::Tuple{Vararg{Any, N}}) where {N}
expr = Expr(:call, :broadcast, :f)
for i in 1:N
if i == 1
push!(expr.args, :(args[1]))
else
push!(expr.args, Expr(:call, :reshape, :(args[$i]), Expr(:tuple, [1 for _ in 1:i - 1]..., :(:))))
end
end
expr
end
outer (generic function with 1 method)
julia> @btime outer($f, ($x, $y, $z));
108.493 ms (3 allocations: 457.76 MiB)