Referencing local variable before assignment results in unexpected behavior

This is julia closures working as intended (imo very unfortunately – I’d love to see this change in julia 2.0): Not just in-place modifications, also reassignments are visible through closures. Your code gets transformed into something like

struct Outer_inner_closure <: Function
n1::Ref{Any}
end
function (instance::Outer_inner_closure)()
instance.n1[] += 1
end
function outer()
n1 = Ref{Any}()
n1[] = 1
inner = Outer_inner_closure(n1)
inner()
return n1[]
end

This is almost never what you want; and if you want it, then you should explicitly allocate a Ref (because the explicit Ref can get proper typing! And if you don’t want rigid typing you can make it a Ref{Any}.)

TLDR: Never ever assign to a closed over variable in julia. It makes code hard to read, and the compiler cannot optimize it, meaning that performance goes to hell.

edit: As evidenced by the way closures work, this was a conscious decision by the design team. My tip against reassignment from closures is an idiosyncratic style preference I stand by, but it is not an official guidance or something. Cf below discussion.

8 Likes