Let’s say I want to automate making lots of very similar looking, but semantically distinct types:
macro make_struct(arg)
quote
struct $(esc(arg))
x
end
export $(esc(arg))
end
end
It creates a struct and then exports it. A quick check:
julia> @macroexpand @make_struct(xxxx)
quote
#= REPL[1]:3 =#
struct xxxx
#= REPL[1]:4 =#
x
end
#= REPL[1]:6 =#
export xxxx
end
So far so good. I may want to process these structs somehow else. So, let’s put their names into a vector and instantiate all the structs from that list:
const structs_to_make = [:Foo, :Bar]
macro make_many_structs()
quote
$([:(@make_struct $(st)) for st in structs_to_make]...)
end
end
But here $(st)
get inserted in the expansion of @make_struct
in two different ways depending where it appears:
julia> @macroexpand @make_many_structs
quote
#= REPL[3]:3 =#
begin
#= REPL[1]:3 =#
struct Main.Foo
#= REPL[1]:4 =#
x
end
#= REPL[1]:6 =#
export Foo
end
begin
#= REPL[1]:3 =#
struct Main.Bar
#= REPL[1]:4 =#
x
end
#= REPL[1]:6 =#
export Bar
end
end
And this will an error in struct
definition. If I escape st
in @make_many_structs
:
macro make_many_structs()
quote
$([:(@make_struct $(esc(st))) for st in structs_to_make]...)
end
end
it doesn’t expand correctly in export
statement:
julia> @macroexpand @make_many_structs
quote
#= REPL[9]:3 =#
begin
#= REPL[1]:3 =#
struct Foo
#= REPL[1]:4 =#
x
end
#= REPL[1]:6 =#
export $(Expr(:escape, :Foo))
end
begin
#= REPL[1]:3 =#
struct Bar
#= REPL[1]:4 =#
x
end
#= REPL[1]:6 =#
export $(Expr(:escape, :Bar))
end
end
Why is it that in one place a symbol gets a qualified name and in another — unqualified? Or is it a bug? Also, any way to workaround?