I did some further test, with the script below:
function f1(x::Float64)
x = x+3.
end
mutable struct MyType{F<:Function}
x::Float64
func::F
funcs::Array{Function,1}
sf::Symbol
function MyType{F}(x::Float64) where {F<:Function}
this = new()
this.x = x
this.funcs = Array{Function,1}(undef,1)
this
end
end
function main()
t1 = MyType{Function}(3.)
t1.func = f1
for i=1:1000000
t1.x = t1.func(i*0.1)
end
end
function main1()
t1 = MyType{Function}(3.)
for i=1:1000000
t1.x = f1(i*0.1)
end
end
function main2()
t1 = MyType{Function}(3.)
f = f1
for i=1:1000000
t1.x = f(i*0.1)
end
end
function main3()
t1 = MyType{Function}(3.)
t1.sf = :f1
f = getfield(Main, t1.sf)
for i=1:1000000
t1.x = f(i*0.1)
end
end
function main4()
t1 = MyType{Function}(3.)
aDict = Dict{String, Function}()
aDict["f1"] = f1
f = get(aDict, "f1", 0)
for i=1:1000000
t1.x = f(i*0.1)
end
end
function main5()
t1 = MyType{Function}(3.)
f = include_string(Main, "f1")
for i=1:1000000
t1.x = f(i*0.1)
end
end
function main6(ff::Function)
t1 = MyType{Function}(3.)
for i=1:1000000
t1.x = ff(i*0.1)
end
end
function main7()
t1 = MyType{Function}(3.)
t1.funcs[1] = f1
for i=1:1000000
t1.x = t1.funcs[1](i*0.1)
end
end
julia> using BenchmarkTools
julia> @btime main()
133.799 ms (4000001 allocations: 61.04 MiB)
julia> @btime main1()
1.640 ns (0 allocations: 0 bytes)
julia> @btime main2()
1.640 ns (0 allocations: 0 bytes)
julia> @btime main3()
133.398 ms (4000001 allocations: 61.04 MiB)
julia> @btime main4()
134.623 ms (4000005 allocations: 61.04 MiB)
julia> @btime main5()
136.345 ms (4000002 allocations: 61.04 MiB)
julia> @btime main6(f1)
1.640 ns (0 allocations: 0 bytes)
julia> @btime main7()
140.606 ms (4000002 allocations: 61.04 MiB)
So it look only “main6” may be not so prohibitive for passing functions. Are there other options please?