Trying to write a macro for simple debugging

Don’t call eval in a macro. A macro shouldn’t actually evaluate any code — you just want to rewrite it — the macro happens before the code is compiled and run (so the variables don’t have values yet). i.e. you would write

macro db(ex)
    quote
        val = $(esc(ex))
        println("@db ", $(string(ex)), " = ", val)
        val
    end
end

giving e.g.

julia> @db 3 + 4
@db 3 + 4 = 7
7

This way, writing @db 3 + 4 is equivalent to writing

begin
    <somevar> = 3 + 4
    println("@db ", "3 + 4", " = ", <somevar>)
    <somevar>
end

where I’m writing <somevar> because macro hygiene causes Julia to rename the val variable to a unique identifier so that it doesn’t conflict with any of your variables. This is what macros do: they rewrite your code, they don’t execute it.

Note that you don’t want to declare ex::Expr, since the argument to the macro could be e.g. a literal number instead of an expression node:

julia> @db 3
@db 3 = 3
3

This kind of macro, by the way, is an exception to my rule that you should generally avoid metaprogramming, because this is something that can really only be done using macros without copy-paste code. It’s so useful that, in fact, it’s built-in as the @show macro as @johnmyleswhite pointed out.

6 Likes