Macro accessing fields of struct at another module

Hello,

I’ve a module with a macro:

julia> 
module MyModule
  export @mymacro

  macro mymacro(T)
          return fieldnames( eval(T) )
  end
end

When I’m at another module or at Julia’s shell I can’t use my macro:

julia> mutable struct Person
              id::Int
              name::String
       end;

julia> using Main.MyModule

julia> @mymacro(Person)
ERROR: LoadError: UndefVarError: Person not defined
Stacktrace:
 [1] top-level scope
   @ :0
 [2] eval
   @ ./boot.jl:368 [inlined]
 [3] eval(x::Symbol)
   @ Main.MyModule ./REPL[1]:2
 [4] var"@mymacro"(__source__::LineNumberNode, __module__::Module, T::Any)
   @ Main.MyModule ./REPL[1]:6
in expression starting at REPL[4]:1

But if this macro is in the same module, like this:

julia>  macro mymacrosamemodule(T)
              return fieldnames( eval(T) )
        end

julia> @mymacrosamemodule(Person)
(:id, :name)

The answer is what I want.

I think the problem is something about Julia Hygiene, and maybe the function esc() could help me, but how to solve this problem?

Thanks

You can write this:

julia> module MyModule
         export @mymacro
         macro mymacro(T)
           @show T typeof(T)  # at macro expansion
           :(fieldnames($(esc(T))))  # returned Expr
         end
       end;

julia> mutable struct Person
          id::Int
          name::String
       end;

julia> using .MyModule

julia> @mymacro Person
T = :Person
typeof(T) = Symbol
(:id, :name)

Although the macro isn’t doing anything, really, it may as well just be a function. One problem with eval (scope/escaping aside) is that the struct this asks about may not even be defined when the macro runs:

julia> f(x::T) where T = @mymacro T;
T = :T
typeof(T) = Symbol

julia> f(Person(1, "me"))
(:id, :name)

julia> struct Dog; id::Int; end

julia> f(Dog(2))
(:id,)
2 Likes