# How to pass an arbitrary number of macro arguments from one macro to another? (a bit like splatting)

**URL:** <https://discourse.julialang.org/t/how-to-pass-an-arbitrary-number-of-macro-arguments-from-one-macro-to-another-a-bit-like-splatting/112288>\
**Category:** General Usage\
**Tags:** macros, metaprogramming\
**Created:** [March 29, 2024, 1:10pm UTC](https://discourse.julialang.org/t/how-to-pass-an-arbitrary-number-of-macro-arguments-from-one-macro-to-another-a-bit-like-splatting/112288 "2024-03-29T13:10:52Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)\
**Post date:** [March 29, 2024, 1:10pm UTC](https://discourse.julialang.org/t/how-to-pass-an-arbitrary-number-of-macro-arguments-from-one-macro-to-another-a-bit-like-splatting/112288/1 "2024-03-29T13:10:52Z")

</div>

I have a macro which does stuff depending on how many inputs there are

```julia
macro my_macro(arg1)
    println("We got one argument.")
    sum = 1
    if arg1 isa Int64
        sum = sum + arg1
    end
    sum
end
macro my_macro(arg1, arg2)
    println("We got two argument.")
    sum = 1
    if arg1 isa Int64
        sum = sum + arg1
    end
    if arg2 isa Int64
        sum = sum + arg2
    end
    sum
end
macro my_macro(arg1, arg2, arg3)
    println("We got three argument.")
    sum = 1
    if arg1 isa Int64
        sum = sum + arg1
    end
    if arg2 isa Int64
        sum = sum + arg2
    end
    if arg3 isa Int64
        sum = sum + arg3
    end
    sum
end

```

(just an example to demonstrate what problem I have)

I then have another macro, which basically is the first macro + some modification. If my macros were functions I could just have done:

```julia
macro my_macor_expanded(args...)
    sum = my_macor_expanded(args...)
    return sum + 1
end

```

Now we are dealing with macros, so that do not work. However, I am not sure how to. E.g.

```julia
macro my_macro_expanded(args...)
    sum = :(@my_macro $args... )
    return sum + 1
end
@my_macro_expanded 1 2

```

even if I have two arguments, the internal `@my_macro` only gets a single one.

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [March 29, 2024, 3:26pm UTC](https://discourse.julialang.org/t/how-to-pass-an-arbitrary-number-of-macro-arguments-from-one-macro-to-another-a-bit-like-splatting/112288/2 "2024-03-29T15:26:09Z")

</div>

I believe you just need another set of parenthesis:

```julia
macro my_macro_expanded(args...)
    sum = :(@my_macro $(args... ))
    return sum + 1
end

```

---

<div class="post-metadata">

**Author:** ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)\
**Post date:** [March 29, 2024, 4:11pm UTC](https://discourse.julialang.org/t/how-to-pass-an-arbitrary-number-of-macro-arguments-from-one-macro-to-another-a-bit-like-splatting/112288/3 "2024-03-29T16:11:21Z")

</div>

That worked, tons of thanks!

---

<div class="post-metadata">

**Author:** ![mnemnion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mnemnion/32/206596_2.png) [@mnemnion](https://discourse.julialang.org/u/mnemnion)\
**Post date:** [March 29, 2024, 6:47pm UTC](https://discourse.julialang.org/t/how-to-pass-an-arbitrary-number-of-macro-arguments-from-one-macro-to-another-a-bit-like-splatting/112288/4 "2024-03-29T18:47:29Z")

</div>

> [@Torkel](#):
>
> I then have another macro, which basically is the first macro + some modification. If my macros were functions I could just have done:
> 
> ```julia
> macro my_macor_expanded(args...)
> sum = my_macor_expanded(args...)
> return sum + 1
> end
> 
> ```
> 
> Now we are dealing with macros, so that do not work.

You can, in fact, call a macro with parenthesis, like a function. It does need the `@` sign.

---

<div class="post-metadata">

**Author:** ![dylanxyz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dylanxyz/32/36646_2.png) [@dylanxyz](https://discourse.julialang.org/u/dylanxyz)\
**Post date:** [March 29, 2024, 8:54pm UTC](https://discourse.julialang.org/t/how-to-pass-an-arbitrary-number-of-macro-arguments-from-one-macro-to-another-a-bit-like-splatting/112288/5 "2024-03-29T20:54:59Z")

</div>

You can also call a macro like this:

```julia
var"@my_macro"( __source__ , __module__ , args...)

```

For your example:

```julia
julia> macro my_macro_expanded(args...)
           sum = var"@my_macro"( __source__ , __module__ , args...)
           return sum + 1
       end
@my_macro_expanded (macro with 1 method)

julia> @my_macro_expanded 1 2
We got two argument.
5

```

---

<div class="post-metadata">

**Author:** ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)\
**Post date:** [March 29, 2024, 10:17pm UTC](https://discourse.julialang.org/t/how-to-pass-an-arbitrary-number-of-macro-arguments-from-one-macro-to-another-a-bit-like-splatting/112288/6 "2024-03-29T22:17:15Z")

</div>

Thanks for the additional comments with more info, that is really useful to know!

---

<div class="post-metadata">

**Author:** ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)\
**Post date:** [March 29, 2024, 11:13pm UTC](https://discourse.julialang.org/t/how-to-pass-an-arbitrary-number-of-macro-arguments-from-one-macro-to-another-a-bit-like-splatting/112288/7 "2024-03-29T23:13:01Z")

</div>

Incidentally, there are some known pitfalls for passing arguments from one macro to another, if you “escape” an argument:

> <https://github.com/JuliaLang/julia/issues/37691>
>
> With nested macro expansion, the inner macro sees an expression generated by the… outer macro which may include \`Expr(:escape)\`. However, macro writers generally test macros only with a single level of expansion, not including \`Expr(:escape)\`.
> 
> This means that macros which pattern match their input are \*incorrect by default\* when used in a nested expansion.
> 
> As a simple example of how pervasive this problem is, consider that \`Base.@view\` cannot generally be used within the AST generated by another macro:
> 
> \`\`\`julia
> julia\> macro m(ex)
> quote
> @view $(esc(ex))
> end
> end
> 
> julia\> A = \[1,2,3\]
> 
> julia\> @m A\[1:2\]
> ERROR: LoadError: ArgumentError: Invalid use of @view macro: argument must be a reference expression A\[...\].
> Stacktrace:
> \[1\] @view(::LineNumberNode, ::Module, ::Any) at ./views.jl:123
> in expression starting at REPL\[9\]:3
> \`\`\`
> 
> The problem here is that \`@view\` gets provided with \`esc(:(A\[1:2\]))\` as an argument, which is not an \`Expr(:ref)\` as naturally expected by the authors of \`@view\`
> 
> This problem occurs whenever macros try to pattern match their input rather than simply substituting it into a larger expression. The pattern matching must be aware that Expr(:escape) \*could occur anywhere\*. Anybody writing macros directly against the Expr API (by using the head field, etc) is going to handle this incorrectly.
> 
> This usability issue has also been discussed at length in https://github.com/JuliaLang/julia/issues/23221. However that issue doesn't describe the problem very clearly as a problem of usability, so I thought I'd restate it here.
> 
> Here's another interesting case:
> 
> \`\`\`julia
> julia\> macro m2(ex)
> quote
> @show $(esc(ex))
> end
> end
> 
> julia\> @m2 1
> $(Expr(:escape, 1)) = 1
> \`\`\`
> 
> \## What to do?
> 
> A possible way forward is to treat this as an \`Expr\` API problem: if pattern matching within macros is incorrect by default, maybe we need better ways to pattern match expressions — for example as in \`MacroTools\` or \`MLStyle\` — ensuring that any appearance of \`Expr(:escape)\` doesn't break the matching process, and returning matched pieces with a correctly nested level of escape.
> 
> A larger overhaul of the macro system as in https://github.com/JuliaLang/julia/pull/6910 has also been mentioned in relation to this. In that PR, \`quote\`ed code created within macros is transformed during lowering, such that every quoted symbol made by the macro is unescaped with \`Expr(:hygenic, sym)\`. I'm not sure whether it solves the problem completely or simply shifts it around to create new and exciting footguns for macro writers.

---

<div class="post-metadata">

**Author:** ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)\
**Post date:** [March 29, 2024, 11:27pm UTC](https://discourse.julialang.org/t/how-to-pass-an-arbitrary-number-of-macro-arguments-from-one-macro-to-another-a-bit-like-splatting/112288/8 "2024-03-29T23:27:05Z")

</div>

Thanks, for mentioning that.

I think i have actually run into this problem in my application. My macro requires me to escape at times, however, this feature fails, which is unfortunate.

Right now I am working around it by implementing my two macros twice (basically identically, but with a small change in the second set, which I initially mostly wanted to re-use the code from the first set).
