Eval() vs @eval

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

Is that to be expected?

1 Like

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

Useful?

1 Like

Nevermind, I figured it out… Silly me, the @eval macro should take an expression as an argument, not a Symbol!

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.

4 Likes

Thanks – I figured it out that I was @evaling a Symbol into existence.

Yessss, thank you! :slight_smile:

1 Like

You can splice expressions into @eval, so you can make your examples work:

julia> ex = :(y = 2)
:(y = 2)

julia> @eval $ex
2

julia> y
2
3 Likes