# Nested expressions rules seem different when \`$\` involved

**URL:** <https://discourse.julialang.org/t/nested-expressions-rules-seem-different-when-involved/82732>\
**Category:** General Usage\
**Tags:** metaprogramming\
**Created:** [June 14, 2022, 8:34am UTC](https://discourse.julialang.org/t/nested-expressions-rules-seem-different-when-involved/82732 "2022-06-14T08:34:30Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 14, 2022, 8:34am UTC](https://discourse.julialang.org/t/nested-expressions-rules-seem-different-when-involved/82732/1 "2022-06-14T08:34:30Z")

</div>

So normally when nesting an expression into an expression, it seems like it doesn’t matter if the latter is written as a quoted `:( ___)` or an `Expr(:quote,___ )`. There’s a difference when the former is written as a quote or an `Expr`, but the nested expressions `eval` to the same inner expression.

```julia
julia> @macroexpand x + 1
:(x + 1)

julia> :( :(x+1) ) == Expr(:quote, :(x+1) )
true
julia> eval( :( :(x+1) ) )
:(x + 1)

julia> :( :(x+1) ) == :( Expr(:call, :+, :x, 1) )
false
julia> eval( :( Expr(:call, :+, :x, 1) ) )
:(x + 1)

```

But things seem to change when the symbol `$` is involved. First, there’s no way to quote the expression `Expr(:$, :x)` parsed from the source code `$x`, which kind of makes sense because `$x` is a syntax error. Second, putting `Expr(:$, :x)` in either a quoted `:( ___)` or an `Expr(:quote,___ )` now makes a difference. The former is more like a nested expression because it `evals` to the inner `Expr(:$, :x)`. The latter is almost what happens in `@eval $x` (and why I started on this train of thought). Third, the latter is somehow equivalent to nesting a different expression `:($x)` in a `:( ___ )`. I can’t really make sense of this.

```julia
julia> x = 3
3
julia> @macroexpand $x 
:($(Expr(:$, :x)))
julia> Expr(:$, :x) # REPL print is redundant
:($(Expr(:$, :x)))

julia> :( Expr(:$, :x) ) == Expr(:quote, Expr(:$, :x) ) # ?!
false
julia> eval( :( Expr(:$, :x) ) )
:($(Expr(:$, :x)))
julia> eval( Expr(:quote, Expr(:$, :x) ) )
3

julia> Expr(:quote, Expr(:$, :x) ) == :( :($x) ) # ?!
true

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [June 14, 2022, 10:12am UTC](https://discourse.julialang.org/t/nested-expressions-rules-seem-different-when-involved/82732/2 "2022-06-14T10:12:47Z")

</div>

I haven’t looked into this particular example too deeply, but probably

[https://github.com/JuliaLang/julia/pull/45426](https://github.com/JuliaLang/julia/pull/45426)

and

[https://github.com/JuliaLang/julia/issues/43054](https://github.com/JuliaLang/julia/issues/43054)

are relevant. The interpolation part you encounter is the remaining edge case jeff mentions in that issue…

---

<div class="post-metadata">

**Author:** ![Sijun](https://avatars.discourse-cdn.com/v4/letter/s/b2d939/32.png) [@Sijun](https://discourse.julialang.org/u/Sijun)\
**Post date:** [October 14, 2022, 2:51am UTC](https://discourse.julialang.org/t/nested-expressions-rules-seem-different-when-involved/82732/3 "2022-10-14T02:51:56Z")

</div>

I believe there is a distinction between `:( Expr(:$, :x) )` and `Expr(:quote, Expr(:$, :x) )`

For a simpler example, consider we have `x=1` and compare `:(x+1)` and `Expr(:quote, x+1)`.  
the `x+1` in `:(x+1)` is just a random string of letters; The compiler(or parser, for that matter) only interprets the meaning when `:(x+1)` gets evaluated.

`x+1` in `Expr(:quote, x+1)`, on the other hand, is computed immediately before we `eval()` it.  
As a result, `Expr(:quote, x+1)` equals `Expr(:quote, 2)`

Similarly, when we do `:( Expr(:$, :x) ) |> eval`, the parser takes the string “Expr(:$, :x)”  
, converts it to `Expr` object and evaluates the `Expr` object to get the final result, which is `Expr(:dollar, :x)` itself. This is what occurs when we type `Expr(:dollar, :x)` in the REPL and the ENTER key.

Howerver in `Expr(:quote, Expr(:$, :x) ) `, the `Expr(:$, :x)` is created (before `eval()` ever occurs). When we use `Expr(:quote, Expr(:$, :x) ) |> eval`, the parser attempts to evaluate the previously constructed `Expr` object, `Expr(:$, :x)`,and the result of doing that is to refer the variable `x`. I believe extracting \_\_\_ from `Expr(:$, :(___)` would be a useful mental modelling of this action.

So rather than `Expr(:quote, Expr(:$, :x))` I believe one possible equivalent form for `:( Expr(:$, :x) )` is `Expr(:quote, Expr(:$, :(Expr(:$, :x))))` .

`Expr(:quote, Expr(:$, :x))` corresponds to `quote; x; end`, rather than `quote; Expr(:$, :x); end` or `:(Expr(:$, :x))`

I said “equivalent”, rather than “equal”, because for example `:(x+1) != quote; x+1; end` but they both mean the same thing. But these are just my thoughts.
