I have the following code that I want to use for storing a vector of functions:
using FunctionWrappers
import FunctionWrappers: FunctionWrapper
abstract type AbstractF end
struct F{P,T,U} <: AbstractF
p::P
f::FunctionWrapper{U,Tuple{T,T,T,U,P}}
end
struct G{P,T,U} <: AbstractF
p::P
f::FunctionWrapper{U,Tuple{T,T,T,U,P}}
end
(F::AbstractF)(a, b, c, d) = F.f(a, b, c, d, F.p)
When I use a vector of functions of say type F
, this is all fine:
function evaluate_list_of_wrappers(wrappers)
nums = zeros(length(wrappers))
for (i, f) in pairs(wrappers)
a, b, c, d = rand(4)
nums[i] = f(a, b, c, d)
end
return nums
end
f1 = (a, b, c, d, p) -> a * b
f2 = (a, b, c, d, p) -> c * p[1]
g1 = (a, b, c, d, p) -> a + b + c
g2 = (a, b, c, d, p) -> a - b + c
p = (1.0, 5)
F1 = F{typeof(p),Float64,Float64}(p, f1)
F2 = F{typeof(p),Float64,Float64}(p, f2)
G1 = G{typeof(p),Float64,Float64}(p, g1)
G2 = G{typeof(p),Float64,Float64}(p, g2)
@code_warntype evaluate_list_of_wrappers((F1, F2)) # Fine
julia> @code_warntype evaluate_list_of_wrappers((F1, F2)) # Fine
MethodInstance for evaluate_list_of_wrappers(::Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}})
from evaluate_list_of_wrappers(wrappers) in Main at Untitled-1:19
Arguments
#self#::Core.Const(evaluate_list_of_wrappers)
wrappers::Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}}
Locals
@_3::Union{Nothing, Tuple{Pair{Int64, F{Tuple{Float64, Int64}, Float64, Float64}}, Int64}}
nums::Vector{Float64}
@_5::Int64
@_6::Int64
f::F{Tuple{Float64, Int64}, Float64, Float64}
i::Int64
d::Float64
c::Float64
b::Float64
a::Float64
Body::Vector{Float64}
1 β %1 = Main.length(wrappers)::Core.Const(2)
β (nums = Main.zeros(%1))
β %3 = Main.pairs(wrappers)::Core.PartialStruct(Base.Pairs{Int64, F{Tuple{Float64, Int64}, Float64, Float64}, Base.OneTo{Int64}, Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}}}, Any[Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}}, Core.Const(Base.OneTo(2))])
β (@_3 = Base.iterate(%3))
β %5 = (@_3::Core.PartialStruct(Tuple{Pair{Int64, F{Tuple{Float64, Int64}, Float64, Float64}}, Int64}, Any[Core.PartialStruct(Pair{Int64, F{Tuple{Float64, Int64}, Float64, Float64}}, Any[Core.Const(1), F{Tuple{Float64, Int64}, Float64, Float64}]), Core.Const(1)]) === nothing)::Core.Const(false)
β %6 = Base.not_int(%5)::Core.Const(true)
βββ goto #4 if not %6
2 β %8 = @_3::Tuple{Pair{Int64, F{Tuple{Float64, Int64}, Float64, Float64}}, Int64}
β %9 = Core.getfield(%8, 1)::Pair{Int64, F{Tuple{Float64, Int64}, Float64, Float64}}
β %10 = Base.indexed_iterate(%9, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
β (i = Core.getfield(%10, 1))
β (@_6 = Core.getfield(%10, 2))
β %13 = Base.indexed_iterate(%9, 2, @_6::Core.Const(2))::Core.PartialStruct(Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, Int64}, Any[F{Tuple{Float64, Int64}, Float64, Float64}, Core.Const(3)])
β (f = Core.getfield(%13, 1))
β %15 = Core.getfield(%8, 2)::Int64
β %16 = Main.rand(4)::Vector{Float64}
β %17 = Base.indexed_iterate(%16, 1)::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(2)])
β (a = Core.getfield(%17, 1))
β (@_5 = Core.getfield(%17, 2))
β %20 = Base.indexed_iterate(%16, 2, @_5::Core.Const(2))::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(3)])
β (b = Core.getfield(%20, 1))
β (@_5 = Core.getfield(%20, 2))
β %23 = Base.indexed_iterate(%16, 3, @_5::Core.Const(3))::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(4)])
β (c = Core.getfield(%23, 1))
β (@_5 = Core.getfield(%23, 2))
β %26 = Base.indexed_iterate(%16, 4, @_5::Core.Const(4))::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(5)])
β (d = Core.getfield(%26, 1))
β %28 = (f)(a, b, c, d)::Float64
β Base.setindex!(nums, %28, i)
β (@_3 = Base.iterate(%3, %15))
β %31 = (@_3 === nothing)::Bool
β %32 = Base.not_int(%31)::Bool
βββ goto #4 if not %32
3 β goto #2
4 β return nums
But if I now include different types, I get an issue:
julia> @code_warntype evaluate_list_of_wrappers((F1, F2, G1, G2)) # ?
MethodInstance for evaluate_list_of_wrappers(::Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}})
from evaluate_list_of_wrappers(wrappers) in Main at Untitled-1:19
Arguments
#self#::Core.Const(evaluate_list_of_wrappers)
wrappers::Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}}
Locals
@_3::Union{Nothing, Tuple{Pair{Int64, AbstractF}, Int64}}
nums::Vector{Float64}
@_5::Int64
@_6::Int64
f::AbstractF
i::Int64
d::Float64
c::Float64
b::Float64
a::Float64
Body::Vector{Float64}
1 β %1 = Main.length(wrappers)::Core.Const(4)
β (nums = Main.zeros(%1))
β %3 = Main.pairs(wrappers)::Core.PartialStruct(Base.Pairs{Int64, AbstractF, Base.OneTo{Int64}, Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}}}, Any[Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}}, Core.Const(Base.OneTo(4))])
β (@_3 = Base.iterate(%3))
β %5 = (@_3::Core.PartialStruct(Tuple{Pair{Int64, AbstractF}, Int64}, Any[Core.PartialStruct(Pair{Int64, AbstractF}, Any[Core.Const(1), F{Tuple{Float64, Int64}, Float64, Float64}]), Core.Const(1)])
=== nothing)::Core.Const(false)
β %6 = Base.not_int(%5)::Core.Const(true)
βββ goto #4 if not %6
2 β %8 = @_3::Tuple{Pair{Int64, AbstractF}, Int64}
β %9 = Core.getfield(%8, 1)::Pair{Int64, AbstractF}
β %10 = Base.indexed_iterate(%9, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
β (i = Core.getfield(%10, 1))
β (@_6 = Core.getfield(%10, 2))
β %13 = Base.indexed_iterate(%9, 2, @_6::Core.Const(2))::Core.PartialStruct(Tuple{AbstractF, Int64}, Any[AbstractF, Core.Const(3)])
β (f = Core.getfield(%13, 1))
β %15 = Core.getfield(%8, 2)::Int64
β %16 = Main.rand(4)::Vector{Float64}
β %17 = Base.indexed_iterate(%16, 1)::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(2)])
β (a = Core.getfield(%17, 1))
β (@_5 = Core.getfield(%17, 2))
β %20 = Base.indexed_iterate(%16, 2, @_5::Core.Const(2))::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(3)])
β (b = Core.getfield(%20, 1))
β (@_5 = Core.getfield(%20, 2))
β %23 = Base.indexed_iterate(%16, 3, @_5::Core.Const(3))::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(4)])
β (c = Core.getfield(%23, 1))
β (@_5 = Core.getfield(%23, 2))
β %26 = Base.indexed_iterate(%16, 4, @_5::Core.Const(4))::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(5)])
β (d = Core.getfield(%26, 1))
β %28 = (f)(a, b, c, d)::Any
β Base.setindex!(nums, %28, i)
β (@_3 = Base.iterate(%3, %15))
β %31 = (@_3 === nothing)::Bool
β %32 = Base.not_int(%31)::Bool
βββ goto #4 if not %32
3 β goto #2
4 β return nums
Namely, I now have f::AbstractF
and %28 = (f)(a, b, c, d)::Any
. Is there any way to get around this with the current setup?