I have a code which calculates complicated integral and which one should be used depends on the parameters. The code is chronically type-unstable (union with Core.Box appears) which makes it few times slower than it should be. The MWE is like this
using QuadGK
function f1(x,b)
x < 0 && ( b = -b )
I, _err = quadgk(t->exp(-t*b),0,1)
return I
end
You can also try b = sign(x)*b, result is the same. In this case I can fix it by switching to
function f2(x,b)
I, _err = if x < 0
quadgk(t->exp(-t*b),0,1)
else
quadgk(t->exp(t*b),0,1)
end
return I
end
But it is hard to understand why this behaviour occurs, and in the full code I have multiple conditions to deal with.
Reassigning a captured variable like b at any point currently makes the lowerer implement it as a Core.Box field in the closure’s type. In your fix, you don’t reassign b, you just switch between different closures. Alternatively, you could capture a new local variable b2 = if x < 0; -b else b end or the branchless b2 = ifelse(x<0, -b, b).
I think this is the usual problem with captured mutated variables in closures (julia#15276). A simple workaround is to re-assign b to a local variable in a let block before capturing it: