# Anonymous function in function closure

Consider the following simple code:

``````function myclass(x)
h() = 1 + x
g() = 2 + x
() -> (h,g)
end
``````

I understand

``````x = 1
a = myclass(x)
a()            #  (>h, >g)
a()() == 2        # = true as this is h()
``````

but why

`a.h() == 2 # true`

which is how the above “class” is meant to be used?

You’re seeing an effect of https://github.com/JuliaLang/julia/pull/13412 which redesigned closures to be `struct`s with fields corresponding to the closed-over values.

When you write:

``````julia> let
a = 1
f() = a + 1
@show f.a
@show f()
end
f.a = 1
f() = 2
``````

the compiler transforms it into (roughly):

``````julia> let
a = 1

# The anonymous funcion is turned into a `struct`
struct Anonymous1{T}
a::T
end
# Make intances of that `struct` type callable
(anon::Anonymous1)() = anon.a + 1
# Make `f` an instance of that `struct` type
f = Anonymous1(a)
@show f.a
@show f()
end
f.a = 1
f() = 2
``````

But the other thing I would say is: don’t use this to implement OOP. Multiple dispatch is a really nice way to organize code, and it’s worth learning the way Julia is intended to be used rather than trying to stick all of your functions inside your types.

4 Likes

Do you know why the `let` block is needed to make your example work? I.e. what’s different at global scope?

At global scope, the closure doesn’t capture the value of `a` but instead just references the global variable directly:

``````julia> a = 1
1

julia> f() = a + 1
f (generic function with 1 method)

julia> a = 5
5

julia> f()
6
``````

Looking at the `code_lowered` shows that the body of `f()` is accessing `Main.a`:

``````julia> @code_lowered f()
CodeInfo(
1 ─ %1 = Main.a + 1
└──      return %1
)
``````

It is indeed surprising that the capture behavior is so different at global vs. local scope.

4 Likes