I define a create_foo macro that declares a function foo.
I want to be able to declare foo functions in the module where the
macro is defined.
This part is OK as this minimal example shows:
module Foo
macro create_foo(X)
quote
$(esc(:foo))(x::$(esc(X))) = 2*x
end
end
println(@macroexpand @create_foo(Int))
# prints :
#
# | begin
# | #= REPL[7]:4 =#
# | foo(var"#7#x"::Int) = begin
# | #= REPL[7]:4 =#
# | 2var"#7#x"
# | end
# | end
#
# which is OK
end
However, I also want Foo module’s users to be able to use this macro to define
specializations. My problem is that, when calling the macro from Main module, I get :
julia> @macroexpand Foo.@create_foo(Float64)
quote
#= REPL[7]:4 =#
foo(var"#9#x"::Float64) = begin
#= REPL[7]:4 =#
2var"#9#x"
end
end
The result I want is a fully qualified name:
julia> @macroexpand Foo.@create_foo(Float64)
quote
#= REPL[7]:4 =#
Foo.foo(var"#9#x"::Float64) = begin
#= REPL[7]:4 =#
2var"#9#x"
end
end
Does my understanding of the problem is right and how to achieve this expected behaviour ?
Macros are expanded in the scope that they’re called from, so the name you’re getting actually is fully qualified, it’s just not the qualification you expected, since it was called in Main instead of Foo.
Here’s one way you can get foo to always be defined in Foo:
module Foo
macro create_foo(X)
qualified_name = esc(GlobalRef(Foo, :foo))
quote
$qualified_name(x::$(esc(X))) = 2*x
end
end
end
julia> @macroexpand Foo.@create_foo(Int)
quote
#= REPL[16]:6 =#
Main.Foo.foo(var"#96#x"::Int) = begin
#= REPL[16]:6 =#
2var"#96#x"
end
end
Creating a function with a macro seems like a fairly common problem to me. Do you have any idea if the way you’re suggesting is the canonical way to solve this problem?