# Calculation of Functions in a loop inside another Function

Hi, I’m looking to calculate nested functions of form f(g(h(...k(x)...)) and have written a function that takes in two arguments. One is called `chain` which is the vector of `Function` defined in the order of their calculation and the input array `x`.

``````function chain_cal(chain:: Vector{Function}, x:: CuArray)
n = size(chain)[1]

for i in 1:n
x = chain[i](x)
end
return x
end
``````

I defined a variable `chain` with two functions named `square`

``````chain = Vector([square, square])
``````
``````2-element Array{typeof(square),1}:
square (generic function with 1 method)
square (generic function with 1 method)
``````

and when I run `chain_cal`, I get an error as follows

``````chain_cal(chain, x)
``````
``````MethodError: no method matching chain_cal(::Array{typeof(square),1}, ::CuArray{Int64,1})
Closest candidates are:
chain_cal(!Matched::Array{Array{Function,1},1}, ::CuArray) at In[16]:1
chain_cal(!Matched::Array{Function,1}, ::CuArray) at In[31]:1

Stacktrace:
[1] top-level scope at In[35]:1
``````

Is there a way where I can modify `chain_cal` such that it accepts all functions or do I have to modify my earlier defined `square` function such that it’s type is `Function`?

``````#=
Square each element in the input CUDA Array
=#
function square(x:: CuArray)
return x.^2
end
``````

The signature does not match since:

``````julia> typeof([square,square]) <: Vector{Function}
false
``````

You can either update:

to `chain_cal(chain::Vector{<:Function}, x::CuArray)` since

``````julia> typeof([square,square]) <: Vector{<:Function}
true
``````

or update

to `Function[square, square]` which would create a `Vector{Function}` and thus match your signature since

``````julia> typeof(Function[square,square]) <: Vector{Function}
true
``````
2 Likes

Thanks.

Can you tell me why the user defined functions are not of type `Function`?

They are subtypes of `Function`:

``````julia> f() = 1
f (generic function with 1 method)

julia> typeof(f) <: Function
true
``````
4 Likes

Creating a unique type for every function allows the compiler to specialize higher-order functions (e.g. `map`) based on the types of their function arguments. You pass an anonymous function to `map` and it may be inlined inside `map`.

1 Like

For a different implementation you could also use `∘` (though I haven’t worked with `CuArray`s, maybe there’s something special about them that interferes?)

I mean something like this:

``````square(x) = x.^2
x = [1,2,3]
chain = [square, square]

julia> ∘(chain...)(x)
3-element Array{Int64,1}:
1
16
81
``````

We can also chain scalar functions and make a broadcast call on the result:

``````chain = [x->x^2, sqrt, inv];   # These functions don't work on vectors...

julia> ∘(chain...).(x)         # but we can use a broadcast call
3-element Array{Float64,1}:
1.0
0.5000000000000001
0.3333333333333333
``````
2 Likes