How to define a vector of Function?

I’m trying to define a Vector{Function} like this:

funvec = Vector{Function}(undef, 3);
for i in 1:3
    fun(theta) = (println(i); cos(theta[1] ^ 3) + 5 * (theta[2] ^ 2) + 10sin(theta[3]) )
    funvec[i] = fun
end

however, upon checking the whole vector contains only the last function:

julia> funvec[1]([0.1, 0.2, 0.3])
3
4.155201566613437

julia> funvec[2]([0.1, 0.2, 0.3])
3
4.155201566613437

julia> funvec[3]([0.1, 0.2, 0.3])
3
4.155201566613437

what’s the proper way to define individual functions?
Thanks

Try replaicing fun(theta) = ... with fun = theta -> ...

2 Likes

what’s the syntax of function definition using -> if I have more than one argument?

Your code actually already works for me (as does @DanielVandH 's suggested modification).

julia> funvec[1](1:3)
1
21.95150238646681

julia> funvec[2](1:3)
2
21.95150238646681

julia> funvec[3](1:3)
3
21.95150238646681
versioninfo
julia> versioninfo()
Julia Version 1.10.4
Commit 48d4fd4843 (2024-06-04 10:41 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: 8 × Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, skylake)
Threads: 8 default, 0 interactive, 4 GC (on 8 virtual cores)
Environment:
  JULIA_NUM_THREADS = auto

I’m using 1.9.2 … but I don’t see changes in 1.10.x about this issue…

At the end of your loop, you have only left a single method of your function fun. Every new definition on the next iteration redefines (overwrites) the same method. That’s why your code does not work as intended.

The syntax suggested in not complete, use this:

funvec = Vector{Function}(undef, 3);
for i in 1:3
    fun = (theta) ->  (println(i); cos(theta[1] ^ 3) + 5 * (theta[2] ^ 2) + 10sin(theta[3]) )
    funvec[i] = fun
end

Example for more than one argument:

(theta, x, y ) -> ...
2 Likes

It’s the same. I just suspected that what’s happening is you’re overwriting the method for fun(theta) so maybe the anonymous function syntax would fix it.

e: Exactly as @oheil says

You can just use brackets: e.g.

julia> f = (x, y, z) -> x + y * z
#1 (generic function with 1 method)

julia> f(1, 2, 3)
7
1 Like

with the -> syntax now I can actually code directly like:

for i in 1:3
    funvec[i] = (theta) ->  (println(i); cos(theta[1] ^ 3) + 5 * (theta[2] ^ 2) + 10sin(theta[3]) )
end

As an attempt to explain the difference between what you and I encounter if it’s not related to the Julia version, could it be you already had (accidentally) defined fun outside of the loop?

E.g.

fun(x) = 0

funvec = Vector{Function}(undef, 3)
for i = 1:3
    fun(x) = x * i
    funvec[i] = fun
end

println(funvec[1](1))  # prints 3
println(funvec[1] == fun == funvec[3])  # true

In that case the explanation of @oheil and @DanielVandH would certainly apply.

I can confirm this is not issue in 1.10.4 version

U’re right. I should have accidentally defined fun.
Thanks

Anyway, the -> syntax is superior in the sense that I could directly assign the function definition into the vector.