Trying to write a macro for simple debugging

I’m trying to wrap my head around macros and wanted to make (what I assumed is) a simple macro which you prefix to an expression in order to get the expression printed with its evaluated value.

Example Let us call the macro @db. What I imagine is the following:

Case 1
--------------
@db 2 + 2
2 + 2 = 4

Case 2
--------------
f(a,b) = begin
  @db a + b
end
f(2, 2)
a + b = 4

It seems to me that I need something along the following lines. But this version doesn’t work!

macro db(ex::Expr)
  :(print($(string(ex)) * " = " * string(eval($ex))))
end

This does the correct thing in case #1, but fails in case #2.

Anyone who can help me provide a working example of a macro like this?

1 Like

To get the value of ex you need to escape it. You will probably find this blog post useful: jkrumbiegel.com - Julia macros for beginners

1 Like

I think you’re looking for @show: https://github.com/JuliaLang/julia/blob/e0a4b7727c2760a61c69c69c1737c46e32223d4f/base/show.jl#L1023

2 Likes

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