What is wrong with this macro:
julia> macro lessthanthree(vec)
return :($vec .< 3)
end
@lessthanthree (macro with 1 method)
julia> @lessthanthree 1:6
ERROR: UndefVarError: .< not defined
Stacktrace:
[1] top-level scope at none:0
The following works:
julia> vec = 1:6
1:6
julia> eval(:($vec .< 3))
6-element BitArray{1}:
true
true
false
false
false
false
try returning esc(:($vec .< 3))
Julia macros are “hygenic” and can’t see values from the scope where they are invocked unless you use esc
.
1 Like
This looks like a bug to me. It doesn’t happen on 1.2-rc1, but does on 1.1, although dump(@macroexpand @lessthanthree 1:6)
looks identical. As ninjaaron says, an overall esc
does seem to avoid it.
This is an error on both 1.1 and 1.2:
julia> @code_lowered 1:6 .< 3
ERROR: UndefVarError: .< not defined
On 0.6.4 you get this warning, and similar on 0.7:
julia> @lessthanthree 1:6
WARNING: .< is no longer a function object; use broadcast(<, ...) instead
1 Like
Thanks, using esc made the macro work for me as well and so does returning :(broadcast(<, $vec, 3))
.
I have read the section about hygiene in the manual and I read it again and I still think I only half get it. Just for my own understanding, assuming it is not a bug, what is it about lessthanthree which might be non-hygienic? Overload of . or <?
Nah, it’s probably a bug. .< Should be accessible in the macro.
On the other hand, that $vec
should be escaped anyway, because otherwise it’s not going to work if you try to pass the macro a variable in another module.