The official documentation says that
@eval expr returns
eval(QuoteNode(expr)). Why not simply
Does it have something to do with interpolation?
The official documentation says that
That’s wrong. It’s returning an expression that
evals the quoted version of
expr, i.e. the expression it returns unquoted is more or less
Sorry, but I still can’t see the difference between the following two macros:
macro m1(expr) eval(QuoteNode(expr)) end
macro m2(expr) expr end
eval above being executed at parse time? And Isn’t
x, in general?
Could you please provide a minimal example where
m2 show different behavior?
What I mean is that the document is wrong. It also does not mean what you write though. The expression in the doc was meant to be the returned expression of the macro, not the implementation of the macro so not,
eval is not executed at parse time. What I said is that the implementation is more or less
Thanks, that helped. Is there a way to see the rewriting steps and not just the final result?
Your example doesn’t work, but you did write “more or less”. This seems to work:
julia> macro my_eval(expr) :(eval($(Expr(:quote, expr)))) end @my_eval (macro with 1 method) julia> a = 1; @my_eval $a 1
Are you looking for
@macroexpand @my_eval $a
Yes that is the “more or less” part.
$ differently. This should be mentioned already in the (dev) doc for expression types/heads but I didn’t check to make sure.
Depending on what you mean as the rewriting step and final result,
@macroexpand gives you the result of the macro which include macro hygiene rewrite but not lowering. If you want to see the bare result of the macro without anything else, you can manually call the macro, which is nothing more than a badly named function…
julia> (@eval Base.$(Symbol("@eval")))(LineNumberNode(1), Main, :aaaa) :(Core.eval(Main, :aaaa))
Do note that you’ll need to be more careful if you want to pass a expression with
$ in. The easiest way I can think of now is to actually write a macro that returns the correctly quoted expression for you, i.e.
julia> macro m(expr) QuoteNode(expr) end @m (macro with 1 method) julia> @m $a :($(Expr(:$, :a))) julia> (@eval Base.$(Symbol("@eval")))(LineNumberNode(1), Main, (@m $a)) :(Core.eval(Main, $(Expr(:quote, :($(Expr(:$, :a))))))) julia> (@eval Base.$(Symbol("@eval")))(LineNumberNode(1), Main, $a) ERROR: syntax: "$" expression outside quote
(Note the use of
QuoteNode in this case)
Note that you can also just look at the definition directly. https://github.com/JuliaLang/julia/blob/8649af9abed7d628567f68bf280113ce05d76d3f/base/essentials.jl#L178 I find all the methods for
@eval by calling
methods on the function
@eval and if you know the signature you want to call it with you can also use
julia> @which @eval a @eval(__source__::LineNumberNode, __module__::Module, ex) in Base at essentials.jl:166
julia> macro call_macro(expr) @assert expr.head == :macrocall return :($(esc(expr.args))($(QuoteNode(expr.args)), $__module__, $(QuoteNode.(expr.args[3:end])...))) end @call_macro (macro with 1 method) julia> @call_macro @eval a :(Core.eval(Main, :a)) julia> @call_macro @eval $a :(Core.eval(Main, $(Expr(:quote, :($(Expr(:$, :a))))))) julia> eval(@call_macro @eval $a) ERROR: UndefVarError: a not defined Stacktrace:  top-level scope at none:0  eval at ./boot.jl:328 [inlined]  eval(::Expr) at ./client.jl:404  top-level scope at none:0 julia> a = 2 2 julia> eval(@call_macro @eval $a) 2
Thanks for the detailed answers. Maybe I’m doing something wrong but
methods doesn’t work with macros so I had to write something like this:
macro methods(expr) is_macro = isa(expr, Expr) && expr.head == :macrocall :(methods($(esc(is_macro ? expr.args : expr)))) end
I’ll start reading the developer’s documentation right now. Sorry if I asked about things that were already explained there.