I expected that the two forms would yield identical results. But to my surprise:
julia> @eval :x
:x
julia> eval(:x)
ERROR: UndefVarError: x not defined
Stacktrace:
[1] top-level scope
[2] eval at ./boot.jl:319 [inlined]
[3] eval(::Symbol) at ./client.jl:389
[4] top-level scope at none:0
OK, they definitely don’t have the same behaviour:
julia> ex = :(x = 2)
:(x = 2)
julia> eval(ex)
2
julia> x
2
julia> ex = :(y = 2)
:(y = 2)
julia> @eval ex
:(y = 2)
julia> y
ERROR: UndefVarError: y not defined
Yes. The input to macros is always converted to an expression, the output is getting evaluated. So, when you do @eval :x, inside the macro the argument is :(:x). When that gets returned, it is evaluated, giving the symbol :x.
By contrast, eval takes as an argument an Expr or Symbol object. So, when it runs, it’s running the code contained in that Expr (or Symbol) which is in this case just x.