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?
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: