Generated Tuples of Functions

Continuing the discussion from Performance and allocation issue with arrays of functions (v1.5):

I want to modify the question I originally posed above, to the case that the collection of functions on which I wish to evaluate may, themselves, be generated. I am thinking of the following example:

@generated function compute_values(x₀, Δt, nΔt, f::Tuple{Vararg{<:Any,K}}) where {K}
    quote
        x = x₀;
        f_vals = zeros($K, nΔt)
        for n in 1:nΔt
            x += 0.5 * Δt * x
            Base.Cartesian.@nexprs $K k -> f_vals[k,n] = (f[k])(x);
        end
        return f_vals
    end
end

x₀ = 1.0;
Δt = 0.5;
nΔt = 10^2;

f_tuple = (x->x.^p for p in 1:5)

compute_values(x₀, Δt, nΔt, f_tuple)

but this gives the error:

MethodError: no method matching compute_values(::Float64, ::Float64, ::Int64, ::Base.Generator{UnitRange{Int64}, var"#3#5"})
Closest candidates are:
  compute_values(::Any, ::Any, ::Any, ::Tuple{Vararg{Any, K}}) where K at In[3]:1

Stacktrace:
 [1] top-level scope
   @ In[6]:1
 [2] eval
   @ ./boot.jl:360 [inlined]
 [3] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
   @ Base ./loading.jl:1094

Any recommendations on how to handle this?

In this case, it is simply that (x->x.^p for p in 1:5) is not a tuple.

Use

f_tuple = ntuple(p -> (x -> x.^p), 5)

or

f_tuple = Tuple(x->x.^p for p in 1:5)

Ok, so that helps with what i had wanted to do. Now here’s a slight wrinkle. I would like to have something like:

Tuple(x->x.^p for p in 1:5, x->sin.(x))

where I have a sequence of functions which are generated from a loop, and then one more function, which I need to specify, and they all need to be grouped together in a single Tuple at the end. Note that the above does not work.

In that case, you may use

((x->x.^p for p in 1:5)..., x->sin.(x))

There might also be variants which are type stable.