"Names" of anonymous functions in loops

I’ve recently been messing around with anonymous functions and loops, trying to generate arrays of functions that are “nested”, i.e. a function generated in a given loop iteration uses functions from previous loop iterations.

I think an example will best explain it.

arr = Array{Function,1}([x -> x + 1])
for i = 1:10
    push!(arr, x -> arr[i](x) + 1)

I start off the array arr with the anonymous function x -> x + 1, and then in each iteration of the loop, push another anonymous function on to the array that takes the previous iteration’s function and adds one to its result: push!(arr, x -> arr[i](x) + 1).

This works as I’d expect, given that the following loop prints the sequence 2 to 12.

for func in arr

But when I look at arr in the REPL, I get:

julia> arr
11-element Array{Function,1}:
 #104 (generic function with 1 method)
 #106 (generic function with 1 method)
 #106 (generic function with 1 method)
 #106 (generic function with 1 method)

It’s always the same pattern – the first element is a certain #-number, and all of the other elements are the same other #-number. Why is this? Like I said, I get the functionality I want, but shouldn’t the #-number be different for every function in the resulting array, as they are “different” functions?

Anonymous functions are implemented by creating a callable struct with a gensymmed name and then creating instances of that struct.

The first one is an instance of the first struct, while the rest are instances of the second.


Just to complement, the struct they are lowered to has a single Int field (or a Ref{Int}, not sure) that will save the i so even for different values of i they end up being the “same” function.

1 Like

for example

julia> fs = [x -> x + i for i = 10:12]
3-element Vector{var"#4#6"{Int64}}:
 #4 (generic function with 1 method)
 #4 (generic function with 1 method)
 #4 (generic function with 1 method)

julia> typeof(fs[1])

julia> typeof(fs[2])

julia> fs[1].i # digging into internals

julia> fs[2].i

julia> fs[1] == fs[2]

As you can see, they are not the same. They just have the same type and print the same.