I am trying to create a struct that contains functions, which will be used to construct a set of differential equations. The complication is that I want to be able to modify the struct’s functions after evaluating the solution of the ODE of these functions. Below is a minimal working example of what I mean:
mutable struct Foo
farr :: Array{Function, 1} # array of functions used to construct a system of ODEs
end
function initfoo() # create "basic" functions
vs = Array{Function, 1}(undef, 2)
f(x) = x^2
g(x) = 1
vs[1] = f
vs[2] = g
Foo(vs) # return new Foo object
end
foo = initfoo() # create Foo object
# Test the original functions
foo.farr[1](2) # == 4
foo.farr[2](2) # == 1 # these work
# Now I want to change the functions
foo.farr[1] = x -> foo.farr[1](x) * (1 + x)
foo.farr[1](1) # this results in a StackOverflowError
It seems I am doing something wrong when I modify the functions in the struct. For my application it is important that I “append” to the original function in the struct. Does anybody know how to fix this?
I just tried this and it still gave the stack overflow error (on evaluation, not on assignment). I also tried copying the function before re-assigning, but alas that did not work either…
This is more generic and captures the old function in a closure:
julia> function nextfunc(old,new)
return x -> new(old(x),x)
end
nextfunc (generic function with 1 method)
julia> vs[1] = x -> x^2
#4471 (generic function with 1 method)
julia> vs[1] = nextfunc(vs[1],(o,x)->o*(1+x))
#4469 (generic function with 1 method)
julia> vs[1](2)
12