(as illustrated in my previous example) we need several tricks to build “good” closure. Following your example:
julia> inc.x
Core.Box(6.6)
julia> getfield(inc, :x)
Core.Box(6.6)
the captured variable x
is a Core.Box
, which is bad.
Now, we need the following tricks:
- even for scalar, use
Array
(of length 1) to store captured variables. - enclose the closure definition by
local <closure_name>
,let <captured_variable> = <captured_variable>
andend
function closuremaker2()
x = [1] # trick 1: to avoid Core.Box, even scalar captured variable needs to be store in an Array
local inc2 # trick 2
let x = x # trick 2
function inc2()
x[1] += 1 # trick 1
x[1] # trick 1
end
end # trick 2
inc2
end
julia> inc2 = closuremaker2()
inc2 (generic function with 1 method)
julia> inc2()
2
julia> inc2.x.contents=5.6
ERROR: type #inc2#5 has no field x
julia> inc2()
3
julia> ind2.x
ERROR: UndefVarError: ind2 not defined
julia> getfield(inc2, :x)
ERROR: type #inc2#5 has no field x
after using these tricks, the captured variable is completed encapsulated (as far as I know): it’s no longer a Core.Box
, and could not be access directly, even with getfield()
.