# Expressions with Arbitrary Objects in their \`args\` Arguments

**URL:** <https://discourse.julialang.org/t/expressions-with-arbitrary-objects-in-their-args-arguments/94771>\
**Category:** Internals & Design\
**Tags:** question, macros, metaprogramming\
**Created:** [February 17, 2023, 5:29am UTC](https://discourse.julialang.org/t/expressions-with-arbitrary-objects-in-their-args-arguments/94771 "2023-02-17T05:29:19Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [February 17, 2023, 5:29am UTC](https://discourse.julialang.org/t/expressions-with-arbitrary-objects-in-their-args-arguments/94771/1 "2023-02-17T05:29:19Z")

</div>

I checked [`Core.Expr`](https://docs.julialang.org/en/v1/base/base/#Core.Expr), [`Core.eval`](https://docs.julialang.org/en/v1/base/base/#Core.eval), [Metaprogramming](https://docs.julialang.org/en/v1/manual/metaprogramming/), and [Julia ASTs](https://docs.julialang.org/en/v1/devdocs/ast/), and I wasn’t able to find an answer. Is this behavior intended and supported?

Let’s build a couple of expressions:

```julia
julia> ax1, ax2 = :([1:5;]), [1:5;]
(:([1:5;]), [1, 2, 3, 4, 5])

julia> ex1, ex2 = :(1 .+ $ax1), :(1 .+ $ax2)
(:(1 .+ [1:5;]), :(1 .+ [1, 2, 3, 4, 5]))

```

Notice that while `ex1` has had an expression interpolated into it, `ex2` has had an _instance_ of `Vector{Int64}` interpolated into it. To confirm:

```julia
julia> dump(ex2)
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol .+
    2: Int64 1
    3: Array{Int64}((5,)) [1, 2, 3, 4, 5]

julia> typeof(ex2.args[3])
Vector{Int64} (alias for Array{Int64, 1})

```

Even though `ex2.args[3]` isn’t an expression, symbol, string, or numeric literal, the expression “just works!™”:

```julia
julia> eval(ex1), eval(ex2)
([2, 3, 4, 5, 6], [2, 3, 4, 5, 6])

```

It also works if you make any other sort of object (mutable or immutable, including user-defined objects) an expression `args` argument.

On the upside, this behavior allows some nice efficiencies—not having to destruct and restruct an object, so `eval` can run faster and the code can sometimes be simpler. On the downside, if you’re not careful, a mutable collection can get accidentally mutated. Example:

```julia
julia> @generated foo(q) = let x = [2]; :($x, q ? $x.^2 : $x, $x.^3) end
       a, b = foo(true), foo(false)
(([2], [4], [8]), ([2], [2], [8]))

julia> a[1][1] = 9
       a, b
(([9], [4], [8]), ([9], [9], [8]))

```

Not a big deal, but it could be worth documenting.

So my question is thus:

> Is this behavior intended and supported?

I ask because I’m pretty sure I’ve inadvertently interpolated objects like this, and if it’s intended then I want to leverage it when I can…

---

<div class="post-metadata">

**Author:** ![Jollywatt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jollywatt/32/202198_2.png) [@Jollywatt](https://discourse.julialang.org/u/Jollywatt)\
**Post date:** [February 21, 2023, 7:26pm UTC](https://discourse.julialang.org/t/expressions-with-arbitrary-objects-in-their-args-arguments/94771/2 "2023-02-21T19:26:25Z")

</div>

I believe @fonsp exploited this ability to have partially evaluated expressions in a demo Pluto notebook, allowing you to “step through time” and see how expressions evaluate from the inside-out.

Forgive me if I remember incorrectly, but I can’t find the notebook now. Any pointers, @fonsp? That was a very cool idea indeed!

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [February 21, 2023, 9:12pm UTC](https://discourse.julialang.org/t/expressions-with-arbitrary-objects-in-their-args-arguments/94771/3 "2023-02-21T21:12:21Z")

</div>

Metaprogramming noob here… but the [docs](https://docs.julialang.org/en/v1/manual/metaprogramming/#Quoting) you linked say at some point

> Expressions provided by the parser generally only have symbols, other expressions, and literal values as their args, whereas expressions constructed by Julia code can have arbitrary run-time values without literal forms as args.

And in an example a bit below that it is stated

```julia
julia> a = 1;

julia> ex = Expr(:call, :+, a, :b)
:(1 + b)

julia> a = 0; b = 2;

julia> eval(ex)
3

```

> - The value of the _variable_ `a` at expression construction time is used as an immediate value in the expression. Thus, the value of `a` when the expression is evaluated no longer matters: the value in the expression is already `1`, independent of whatever the value of `a` might be.

Sounds like it’s really the _value_ of the variable that will be used in an `Expr`, whatever it might be. Is this the behavior that you are referring to, or did I miss something?

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [February 21, 2023, 9:20pm UTC](https://discourse.julialang.org/t/expressions-with-arbitrary-objects-in-their-args-arguments/94771/4 "2023-02-21T21:20:06Z")

</div>

> [@uniment](#):
>
> Is this behavior intended and supported?

Yes

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [February 21, 2023, 10:50pm UTC](https://discourse.julialang.org/t/expressions-with-arbitrary-objects-in-their-args-arguments/94771/5 "2023-02-21T22:50:33Z")

</div>

> [@Sevi](#):
>
> whereas expressions constructed by Julia code can have arbitrary run-time values _ **without literal forms** _ as args

Ah, that was the key phrase I had missed! Thanks for the spot!

(There’s an example of interpolating a `Tuple`, which in retrospect should have been sufficient for me, but for some reason my mind dismissed its relevance due to it being `isbits`.)

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [February 22, 2023, 11:19am UTC](https://discourse.julialang.org/t/expressions-with-arbitrary-objects-in-their-args-arguments/94771/6 "2023-02-22T11:19:14Z")

</div>

An example of this in Base Julia is the regex string macro, as you can see here it directly puts the `Regex` object into the AST:

> <https://github.com/JuliaLang/julia/blob/6412a56223e38824ce6eff78bf34662637971e1c/base/regex.jl#L123>

---

<div class="post-metadata">

**Author:** ![fonsp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fonsp/32/222349_2.png) [@fonsp](https://discourse.julialang.org/u/fonsp)\
**Post date:** [April 8, 2023, 12:36pm UTC](https://discourse.julialang.org/t/expressions-with-arbitrary-objects-in-their-args-arguments/94771/7 "2023-04-08T12:36:21Z")

</div>

This is in [PlutoTest.jl](https://github.com/JuliaPluto/PlutoTest.jl) 😊
