Because the same code will behave differently in global vs local scope, if one wants to write a macro which can work in both, in theory it needs to know into which scope its being expanded, right?
I’m running into this trying to a solve a problem with UnPack. I noticed that @unpack
accidently leaks variables into toplevel scopes, because it roughtly expands e.g. @unpack x = foo()
to
varXXX = foo()
x = varXXX.x
varXXX
(The reason for doing this is to return the entire contents of foo()
, rather than just the unpacked variables, consistent with Julia tuple unpacking)
This is fine in a local scope, but in a global scope it leaves all these gensym’ed varXXX
variables around whose memory never gets GC’ed.
To fix this, you’d want to expand instead into the following in a global scope (but keep the original thing in a local scope, since the following would not work there correctly):
# when expanding into a global scope:
let varXXX = foo()
global x = varXXX.x
varXXX
end
Since macro’s currently don’t know which scope they’re in, you can’t do it. As far as I can tell, no other workaround is currently possible in Julia at all, so its impossible to write an @unpack
macro which works in both scopes. If the macro could branch on something like if __istoplevel__
or something, then it would be straightforward though.
(FWIW, another place this would be useful is in my Memoization.jl package where caches need to be cleared on redefinition only in the global scope, although there, unlike here, there does exist a workaround, but which is pretty ugly)
Any thoughts on if something like this could be added? Or other potential workarounds?