Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disambiguate the various quoting mechanisms in Julia metaprogramming

Could someone lay out clearly the various quoting mechanisms available for metaprogramming in Julia, and illustrate each one with a minimal example?

So that it is clear which to use in which situation...

As far as I can see there is:

  • :(someExpr; maybeMore)
  • quote; ...expressions... end; which is almost the same as the above only with line numbers for debug purposes
  • Expr(:quote, x) which (according to @totalverb) is equivalent to Meta.quot(x)
  • QuoteNode which (according to Jeff Bezanson) "is only used in the internal AST representation, not by macros. It's safe to ignore unless you work on later stages of the compiler."

Is this list comprehensive? Am I missing out any alternate representations?

like image 463
P i Avatar asked Dec 11 '16 17:12

P i


1 Answers

:... is the default quoting mechanism. It parses an expression and returns the AST.

:x == Symbol("x")

:(x + y) == Expr(:call, :+, :x, :y)

:(x; y; z) == Expr(:block, :x, :y, :z)

eval(:<expr>) should return the same as just <expr> (assuming <expr> is a valid expression in the current global space)

eval(:(1 + 2)) == 1 + 2

eval(:(let x=1; x + 1 end)) == let x=1; x + 1 end

quote ... end is the same as :(begin ... end)


Expr(:quote, x) is used to represent quotes within quotes.

Expr(:quote, :(x + y)) == :(:(x + y))

Expr(:quote, Expr(:$, :x)) == :(:($x))

QuoteNode(x) is similar to Expr(:quote, x) but it prevents interpolation.

eval(Expr(:quote, Expr(:$, 1))) == 1

eval(QuoteNode(Expr(:$, 1))) == Expr(:$, 1)

Here's a macro using all of them:

macro quoted(expression)
    quote
        println("received expression: :(", $(QuoteNode(expression)), ")")
        $(Expr(:quote, expression))
    end
end

Usage:

julia> x = 1
1

julia> @quoted $x + 1
received expression: :($(Expr(:$, :x)) + 1)
:(1 + 1)

julia> @quoted :(x + 1)
received expression: :($(Expr(:quote, :(x + 1))))
:($(Expr(:quote, :(x + 1))))

edit: Meta.quot(x) is indeed the same as Expr(:quote, x). It's undocumented and isn't mentioned anywhere, but it was a conscious addition to the functions exported by Base (https://github.com/JuliaLang/julia/pull/1755) and I haven't seen any plans to deprecate it, so you can use it.

like image 149
phicr Avatar answered Oct 15 '22 20:10

phicr