# Vector of functions

I am trying to encode a Vector of functions. I wrote the following:

``````# Does not work if I replace function by AbstractFunction
a = Vector{Function}(undef, 5)
for i in 1:5
a[i](t) = cos(i*t)
end
``````

I get the error:

`````` ERROR: syntax: invalid function name "a[i]" around /Users/erlebach/src/2022/rude/giesekus/alex_broken_code_2023-02-17/rude_impl.jl:3
Stacktrace:
 top-level scope
@ ~/src/2022/rude/giesekus/alex_broken_code_2023-02-17/rude_impl.jl:2
``````

I do not understand why this error occurs. Any insight is appreciated.

It thinks you’re trying to define a function named `a[i]`, which isn’t allowed. Instead you want an anonymous function.

``````julia> for i in 1:5
a[i] = t -> cos(i*t)
end

julia> a(τ)
1.0
``````
6 Likes

``````ct = [ (t) -> 3*cos(1*t), (t) -> 3*cos(2*t), (t) -> 3*cos(3*t), (t) -> 3*cos(4*t), (t) -> 3*cos(5*t) ]
``````

So I can create a comprehension and update the function with a lambda function.

1 Like

Note that, because `Function` is an abstract type, accessing the elements of a `Vector{Function}` will be type-unstable and cause performance degradation:

``````julia> d = [t->cos(0t), t->cos(1t), t->cos(2t), t->cos(3t)]
4-element Vector{Function}:
#3 (generic function with 1 method)
#4 (generic function with 1 method)
#5 (generic function with 1 method)
#6 (generic function with 1 method)

julia> d(π/4), d(π/4)
(1.0, -0.7071067811865475)

julia> using BenchmarkTools

julia> @btime \$d(0)
20.888 ns (1 allocation: 16 bytes)
1.0
``````

Notice that `d`’s element type is `Function`, which is an abstract type.:

``````julia> isabstracttype(Function)
true
``````

this is necessary because each anonymous function inside it is of a different type.

By contrast, a comprehension that generates lambdas will produce a type-stable array:

``````julia> e = [t->cos(i*t) for i=0:3]
4-element Vector{var"#12#14"{Int64}}:
#12 (generic function with 1 method)
#12 (generic function with 1 method)
#12 (generic function with 1 method)
#12 (generic function with 1 method)

julia> e(π/4), e(π/4)
(1.0, -0.7071067811865475)

julia> @btime \$e(0)
4.000 ns (0 allocations: 0 bytes)
1.0
``````

Notice that `e`’s element type is `var"#12#14"{Int64}`, which is a concrete type:

``````julia> isabstracttype(var"#12#14"{Int64})
false
``````

Even though all the functions contained in `e` are of the same type, they perform the desired task. This is because internally they’re just callable `struct`s which capture the value of `i`.

``````julia> Tuple(e[j].i for j=eachindex(e))
(0, 1, 2, 3)
``````
6 Likes

Alternatively:

``````getproperty.(e, :i)
``````
2 Likes

Can I use Zygote on `e` for example? The answer should be yes. I have not tried it.