I want to define a macro similar to those in the code below, where the function f
is evaluated in the scope where the macro is expanded, but default
is evaluated in module A
.
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.5.3 (2020-11-09)
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |
julia> module A
macro p() quote $(esc(:f))(x=default) = 1 end end
macro q() quote function $(esc(:f)) end end end
macro r() quote function $(:f) end end end
macro s() quote f(x=default) = 1 end end
macro t() :( f(x=default) = 1 ) end
end
Main.A
julia> using .A: @p, @q, @r, @s, @t
julia> @macroexpand @p
quote
#= none:2 =#
f(var"#1#x" = Main.A.default) = begin
#= none:2 =#
1
end
end
julia> @macroexpand @s
quote
#= none:5 =#
var"#2#f"(var"#3#x" = Main.A.default) = begin
#= none:5 =#
1
end
end
This is consistent with the manual. Defining f
as a function is like assigning to it, so it’s a local variable. (It would be nice if the manual said that explicitly.) Unless it is escaped, it is replaced by a gensym.
julia> @macroexpand @q
:($(Expr(:error, "malformed expression")))
julia> @macroexpand @r
quote
#= none:4 =#
function var"#4#f" end
end
That’s odd: esc(:f)
works in some contexts, but not in others. Is there a way to do what @q
is trying to do?
julia> @macroexpand @t
:(Main.A.f(var"#5#x" = Main.A.default) = begin
#= none:6 =#
1
end)
That’s also odd. By my reading of the manual, f
should refer to the same thing in @t
as it does in @s
.