Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quote-unquote idiom in Julia & concatenating Expr objects

I'd like to write a simple macro that shows the names & values of variables. In Common Lisp it would be

(defmacro dprint (&rest vars)
  `(progn
    ,@(loop for v in vars
            collect `(format t "~a: ~a~%" ',v ,v))))

In Julia I had two problems writing this:

  1. How can I collect the generated Expr objects into a block? (In Lisp, this is done by splicing the list with ,@ into progn.) The best I could come up with is to create an Expr(:block), and set its args to the list, but this is far from elegant.
  2. I need to use both the name and the value of the variable. Interpolation inside strings and quoted expressions both use $, which complicates the issue, but even if I use string for concatenation, I can 't print the variable's name - at least :($v) does not do the same as ',v in CL...

My current macro looks like this:

macro dprint(vars...)
  ex = Expr(:block)
  ex.args = [:(println(string(:($v), " = ", $v))) for v in vars]
  ex
end

Looking at a macroexpansion shows the problem:

julia> macroexpand(:(@dprint x y))
quote 
    println(string(v," = ",x))
    println(string(v," = ",y))
end

I would like to get

quote 
    println(string(:x," = ",x))
    println(string(:y," = ",y))
end

Any hints?

EDIT: Combining the answers, the solution seems to be the following:

macro dprint(vars...)
  quote
    $([:(println(string($(Meta.quot(v)), " = ", $v))) for v in vars]...)
  end
end

... i.e., using $(Meta.quot(v)) to the effect of ',v, and $(expr...) for ,@expr. Thank you again!

like image 554
vukung Avatar asked Oct 08 '16 10:10

vukung


1 Answers

the @show macro already exists for this. It is helpful to be able to implement it yourself, so later you can do other likes like make one that will show the size of an Array..

For your particular variant: Answer is Meta.quot,

macro dprint(vars...)
     ex = Expr(:block)
     ex.args = [:(println($(Meta.quot(v)), " = ", $v)) for v in vars]
     ex
end

See with:

julia> a=2; b=3;

julia> @dprint a
a = 2

julia> @dprint a b
a = 2
b = 3
like image 103
Lyndon White Avatar answered Sep 18 '22 13:09

Lyndon White