# How to reference argument of expression

**URL:** <https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213>\
**Category:** New to Julia\
**Tags:** macros, metaprogramming\
**Created:** [April 28, 2022, 1:45pm UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213 "2022-04-28T13:45:46Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [April 28, 2022, 1:45pm UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/1 "2022-04-28T13:45:46Z")

</div>

Hi,

I’m trying to make an alias to an argument of an expression within a macro, and then change it to something else. Something like:

```julia
macro foo(exp)
   arg1 = exp.args[1]
   arg1 = 3
end

```

However, I find that if I do this, arg1 is actually a copy, and not a reference, to exp.args[1]. How can I do this without having to type exp.args[1] all the time?

---

<div class="post-metadata">

**Author:** ![cmarcotte](https://avatars.discourse-cdn.com/v4/letter/c/a3d4f5/32.png) [@cmarcotte](https://discourse.julialang.org/u/cmarcotte)\
**Post date:** [April 28, 2022, 2:17pm UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/2 "2022-04-28T14:17:12Z")

</div>

I think if you use a [`view`](https://docs.julialang.org/en/v1/base/arrays/#Views-(SubArrays-and-other-view-types)) it should work.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 28, 2022, 4:56pm UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/3 "2022-04-28T16:56:40Z")

</div>

See: [Assignment and mutation - #4 by StefanKarpinski](https://discourse.julialang.org/t/assignment-and-mutation/19119/4)

(As usual, I would encourage you to [think twice about doing metaprogramming](https://discourse.julialang.org/t/how-to-warn-new-users-away-from-metaprogramming/35022/22), especially when you are still learning the basics of Julia.)

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 28, 2022, 5:00pm UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/4 "2022-04-28T17:00:56Z")

</div>

> [@cmarcotte](#):
>
> I think if you use a [`view`](https://docs.julialang.org/en/v1/base/arrays/#Views-(SubArrays-and-other-view-types)) it should work.

Yes, but then `arg1` is a zero-dimensional array and you need to mutate its contents with `arg1[] = ...`.

```julia
julia> ex = :(3 + 4 * 7)
:(3 + 4 * 7)

julia> ex.args
3-element Vector{Any}:
  :+
 3
  :(4 * 7)

julia> arg = @view ex.args[2]
0-dimensional view(::Vector{Any}, 2) with eltype Any:
3

julia> arg[] = 111
111

julia> ex
:(111 + 4 * 7)

```

This is a pretty unusual style of Julia programming, however, especially in a metaprogramming context.

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [May 3, 2022, 11:07am UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/5 "2022-05-03T11:07:23Z")

</div>

So is there a different option?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 3, 2022, 1:12pm UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/6 "2022-05-03T13:12:04Z")

</div>

> [@f.ij](#):
>
> So is there a different option?

What is your overall goal here? Why are you using macros in the first place? We need some background to answer intelligently, to avoid falling into the trap of an [XY problem](https://xyproblem.info/).

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [May 3, 2022, 10:28pm UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/7 "2022-05-03T22:28:51Z")

</div>

You can compute what you want to assign and then write out `exp.args[1]` only once as the left hand side of one assignment. Also, I’m curious what languages work the way you were wanting this to work.

---

<div class="post-metadata">

**Author:** ![o314](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/o314/32/252_2.png) [@o314](https://discourse.julialang.org/u/o314)\
**Post date:** [May 4, 2022, 4:18am UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/8 "2022-05-04T04:18:48Z")

</div>

I think there will be a mismatch between the part of the language you are targeting (meta programming, lisp based) and your approach of programming (imperative programming, with mutable cell popping here and there, suddenly but exactly when?) . Sadly, still not enough people are correctly trained about FP today, one should have a look to those two books before going to deeply in julia core IMO

> **[Structure and Interpretation of Computer Programs](https://en.wikipedia.org/wiki/Structure_and_Interpretation_of_Computer_Programs)**
>
> Structure and Interpretation of Computer Programs (SICP) is a computer science textbook by Massachusetts Institute of Technology professors Harold Abelson and Gerald Jay Sussman with Julie Sussman. It is known as the "Wizard Book" in hacker culture. It teaches fundamental principles of computer programming, including recursion, abstraction, modularity, and programming language design and implementation.
> MIT Press published the first edition in 1984, and the second edition in 1996. It was formerl...

> **[How to Design Programs](https://en.wikipedia.org/wiki/How_to_Design_Programs)**
>
> How to Design Programs (HtDP) is a textbook by Matthias Felleisen, Robert Bruce Findler, Matthew Flatt, and Shriram Krishnamurthi on the systematic design of computer programs. MIT Press published the first edition in 2001, and the second edition in 2018, which is freely available online and in print. The book introduces the concept of a design recipe, a six-step process for creating programs from a problem statement. While the book was originally used along with the education project TeachSche...

Included bonus : be able to explain without any culture shock sims and diffs between

```julia
@test cdr(1, 2) == cdr((1, 2)) == (2,)
@test cdr([1, 2]) == [2]

```

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [May 4, 2022, 9:06am UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/9 "2022-05-04T09:06:53Z")

</div>

I was looking at this tutorial: [Introduction to metaprogramming in Julia | Workshop | JuliaCon 2021](https://www.youtube.com/watch?v=2QLhw6LVaq0&t=3352s). Following the things he did, I was just trying stuff out and I wanted to make a macro to allow for negative indexing of vectors ala Python. E.g. I can write `@ni vec[-1]` to reference the end of a vector etc. In the video, at around the 55:50 mark the guy in the video does something that I thought to be useful for such a macro, because I can directly reference the -1 and just turn it into the appropriate index. However, the guy in the video himself confesses he is a bit surprised that you can not reference these arguments within the code, which is why I decided to ask.

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [May 4, 2022, 9:10am UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/10 "2022-05-04T09:10:12Z")

</div>

Right, that’s of course also a way to do it. I don’t know about other languages and their approach to meta programming , since this is my first foray into meta programming at all. In my post above I explain that I was following a tutorial which went over this topic and I was trying to follow what was done there.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 4, 2022, 11:24am UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/11 "2022-05-04T11:24:48Z")

</div>

> [@f.ij](#):
>
> Following the things he did, I was just trying stuff out and I wanted to make a macro to allow for negative indexing of vectors ala Python.

Thanks for the context. Implementing negative indexing is indeed a nice learning exercise.

Note, however, that this is not a great practical use-case for macros. The reason is that macros only know how expressions _look_, not what they _mean_. If you have an expression `x[-1]`, a macro can see that you have a negative index and turn this into `x[end]`, but if you have an expression `x[i]`, a macro doesn’t have access to the value of `i` or even whether it is a number at all. e.g. it could transform `x[i]` to `x[i < 0 ? (end+i+1) : i]`, but that would fail if `i` is not an integer index (e.g. `i` could be an array).

Instead, if you wanted to fully support negative indexing, probably you would need to implement a new array type, wrapping an ordinary Julia array, with `getindex` method that checks whether each index is negative and transforms it accordingly. (That would slow down indexing, but so does negative indexing in Python … it’s just that a slight slowdown of scalar indexing in Python doesn’t matter because Python is slow to begin with.)

> [@f.ij](#):
>
> I don’t know about other languages and their approach to meta programming

The point is that this is not about metaprogramming, it’s just about programming—macros are just ordinary Julia functions that happen to be called on parsed expressions. It would be very rare to see a computer language where:

```julia
x = a[i]
x = y

```

changes `a[i]`. (I can’t think of any off the top of my head.)

For example, here is an `@ni` macro that works only on literal integer indices, and doesn’t do any mutation of the arguments at all — it just constructs a completely new argument list to return:

```julia
macro ni(ex)
    if Meta.isexpr(ex, :ref)
        newargs = map(ex.args[2:end]) do i
            i isa Integer && i < 0 ? :($(:end) - $(-i-1)) : i
        end
        return Expr(:ref, esc(ex.args[1]), esc.(newargs)...)
    else
        return ex
    end
end

```

You can see what it does using `macroexpand`:

```julia
julia> macroexpand(Main, :(@ni x[3,-2]))
:(x[3, end - 1])

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 4, 2022, 11:36am UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/12 "2022-05-04T11:36:05Z")

</div>

> [@o314](#):
>
> I think there will be a mismatch between the part of the language you are targeting (meta programming, lisp based) and your approach of programming (imperative programming)

Metaprogramming in Julia is not really any less imperative than the rest of the language — a macro in Julia is basically just an ordinary Julia function that happens to be called at an unusual time (at code-lowering time, right after parsing but before compilation); you can implement it in an imperative style if you want.

Rather, I think this is the usual [confusion between assignment and mutation](https://discourse.julialang.org/t/assignment-and-mutation/19119/4) that arises in all imperative languages that use the same `=` symbol for both.

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [May 4, 2022, 12:52pm UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/13 "2022-05-04T12:52:05Z")

</div>

> It would be very rare to see a computer language where: …

Right I see, although this is basically what references do in C++ right?

I do see your point though, and indeed I realise what was done in the video that I mentioned was a bit different from what I was asking. What he tried to do there is

```julia
piece = code.args[2]
piece.args[3] = 3

```

So it was a composite objects where one of the arguments contained more arguments. Here the assignment of `piece.args[3]` doesn’t change the original code.  
This is more akin to something like this

```julia
struct foo
   vec::Vector{Any}
end
bar = foo([1,2,3])

v = bar.vec
v[3] = 4

```

Which of course changes `bar.vec` to `[1,2,4]`. You’re completely right however that what I was trying to doo doesn’t work, and I know that that normally doesn’t work, likewise for other languages like Python.

I think I was thrown off by the above example however, and it’s still not clear to me why that doesn’t work.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 4, 2022, 1:22pm UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/14 "2022-05-04T13:22:02Z")

</div>

> [@f.ij](#):
>
> it’s still not clear to my why that doesn’t work.

Can you give a complete, runnable example of this? I don’t want to have to go through the video to find the code you are talking about.

---

<div class="post-metadata">

**Author:** ![o314](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/o314/32/252_2.png) [@o314](https://discourse.julialang.org/u/o314)\
**Post date:** [May 5, 2022, 10:03pm UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/15 "2022-05-05T22:03:45Z")

</div>

> [@stevengj](#):
>
> Metaprogramming in Julia is not really any less imperative than the rest of the language

I just can count how many times i strongly disagree with that.  
A quick fact : the count of cdr call in julia lowerer, by julia version

| count | julia version | |
| --- | --- | --- |
| 201 | julia v1.0.0 | [https://github.com/JuliaLang/julia/blob/v1.0.0/src/julia-syntax.scm](https://github.com/JuliaLang/julia/blob/v1.0.0/src/julia-syntax.scm) |
| 215 | julia v1.5.1 | [https://github.com/JuliaLang/julia/blob/v1.5.1/src/julia-syntax.scm](https://github.com/JuliaLang/julia/blob/v1.5.1/src/julia-syntax.scm) |
| 249 | julia v1.7 | [https://github.com/JuliaLang/julia/blob/v1.7.0/src/julia-syntax.scm](https://github.com/JuliaLang/julia/blob/v1.7.0/src/julia-syntax.scm) |

The less one can say, is that the less you know cdr is not the more you will understand the evolution of the julia metaprogramming system

* * *

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 5, 2022, 10:15pm UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/16 "2022-05-05T22:15:17Z")

</div>

> [@o314](#):
>
> A quick fact : the count of cdr call in julia lowerer, by julia version

That’s not “metaprogramming in Julia”. It’s the Julia parser, which is written in Scheme (which is of course a mainly functional language). “Metaprogramming” here refers to **Julia code** that is called _after_ the parser is run (e.g. via macros).

In particular, the body of a macro definition is just standard Julia code that happens to be acting on an `Expr` object. It’s therefore no more or less functional than the rest of the Julia language — you can implement it in a functional style if you want, but you can also write the macro body in an imperative style.

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [May 10, 2022, 11:44am UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/17 "2022-05-10T11:44:25Z")

</div>

Yes, here it is

```julia
code = Meta.parse("j = i^2")

piece = code.args[2] # returns :(i ^ 2)

piece.args[3] # returns 2

piece.args[3] = 3

piece # returns :(i ^ 3)

code # returns :(j = i ^ 2)

code.args[2].args[3] = 3

code # now returns :(j = i ^ 3)

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 10, 2022, 11:49am UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/18 "2022-05-10T11:49:00Z")

</div>

> [@f.ij](#):
>
> `code # returns :(j = i ^ 2)`

I can’t reproduce:

```julia
julia> code = Meta.parse("j = i^2")
:(j = i ^ 2)

julia> piece = code.args[2]
:(i ^ 2)

julia> piece.args[3] = 3
3

julia> code
:(j = i ^ 3)

```

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [May 10, 2022, 12:15pm UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/19 "2022-05-10T12:15:24Z")

</div>

That’s weird. I got this exactly from the video I mentioned. I didn’t check it myself though. Maybe this was changed in a newer Julia version?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 10, 2022, 12:50pm UTC](https://discourse.julialang.org/t/how-to-reference-argument-of-expression/80213/20 "2022-05-10T12:50:07Z")

</div>

> [@f.ij](#):
>
> Maybe this was changed in a newer Julia version?

Nope, it does exactly the same thing in Julia 0.3 from 2015:

```julia
   _ _ _(_)_ | A fresh approach to technical computing
  (_) | (_) (_) | Documentation: http://docs.julialang.org
   _ _ _| |_ __ _ | Type "help()" for help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 0.3.12 (2015-10-26 12:41 UTC)
 _/ |\ __'_|_|_|\__'_| | Official http://julialang.org/ release
|__/ | x86_64-apple-darwin13.4.0

julia> code = Meta.parse("j = i^2")
:(j = i^2)

julia> piece = code.args[2]
:(i^2)

julia> piece.args[3] = 3
3

julia> code
:(j = i^3)

```

I haven’t watched the video closely, but it looks like @dpsanders was running in a Jupyter notebook — maybe he accidentally evaluated the code cells out of order?
