Confused by macros and their hygene

Hello

I know there is a simple solution to this but my search skills have failed me. Suppose I have a a macro like

macro P(ex)
    return quote
        if Print
            println($ex)
        end
    end
end

then Print=true and @P “text” will work
@macroexpand @P “text” shows why

but how can I do this inside a function?

function f()
  Print=true
   @P "text"
end

I read all I can find about macro hygene and esc() and still I cannot make it work.

I know there is something incredibly simple that escapes me.

best, Jack

You’ll see in the macroexpanded expression:

julia> @macroexpand @P "text"
quote
    #= REPL[1]:3 =#
    if Main.Print
        #= REPL[1]:4 =#
        Main.println("text")
    end
end

that Print refers to Main.Print, which is a global that’s expected to exist in the Main module, but in f you want it to refer to a local variable called Print. You’ll need to esc the Print in your returned expression from the macro:

julia> macro P(ex)
           return quote
               if $(esc(:Print))
                   println($ex)
               end
           end
       end
@P (macro with 1 method)

julia> @macroexpand @P "text"
quote
    #= REPL[3]:3 =#
    if Print
        #= REPL[3]:4 =#
        Main.println("text")
    end
end
2 Likes

Mike

Wow, I knew it was something simple, in my case I understood esc, but not :Print vs. Print, I see the difference now. I will redouble my efforts to understand metaprogramming on a deeper level.

This is why Julia is so great, the helpfulness of the community. Thanks Mike.

best Jack

1 Like

I humbly dispute this assertion.

I enjoyed Julia for years without any contact with the “community” :slight_smile:

1 Like