State of closures, Fix1/Fix2

Oh I just realized deepcopy still gets applied every time that function runs. So if I just create another variable and add it to the expression, boxing doesn’t happen. THAT’s how Fix2 solves the problem.

julia> function abmult(r::Int)
                  if r < 0
                      r = -r
                  end
                  r1 = deepcopy(r); f(x) = r1*x
                  return f
              end
abmult (generic function with 1 method)

julia> f = abmult(4); @code_warntype f(2)
MethodInstance for (::var"#f#3"{Int64})(::Int64)
  from (::var"#f#3")(x) @ Main REPL[7]:5
Arguments
  #self#::var"#f#3"{Int64}
  x::Int64
Body::Int64
1 ─ %1 = Core.getfield(#self#, :r1)::Int64
│   %2 = (%1 * x)::Int64
└──      return %2

So I guess that means if you’re working with closures, don’t capture a variable that gets reassigned to (or at least be VERY careful about it). I’m actually very careful about reassigning variables anyway because I got burned by type instabilities before. I can see why you wouldn’t want to capture something like this.

1 Like