# Macros with multiple parameters

**URL:** <https://discourse.julialang.org/t/macros-with-multiple-parameters/74120>\
**Category:** General Usage\
**Tags:** macros\
**Created:** [January 6, 2022, 5:28am UTC](https://discourse.julialang.org/t/macros-with-multiple-parameters/74120 "2022-01-06T05:28:44Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![gcv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gcv/32/11086_2.png) [@gcv](https://discourse.julialang.org/u/gcv)\
**Post date:** [January 6, 2022, 5:28am UTC](https://discourse.julialang.org/t/macros-with-multiple-parameters/74120/1 "2022-01-06T05:28:44Z")

</div>

I’m having trouble with macros taking multiple parameters. Specifically, I’m writing a macro which needs to take `@ __DIR__ ` and an expression as its arguments. Here’s a simplified example:

```julia
macro tm1(dir, action)
   :(begin
        println("tm1 dir: ", $dir)
        $action
     end)
end

```

The following invocation fails:

```julia
@tm1 @ __DIR__ begin
   3 + 3
end

```

The error is:

```nohighlight
ERROR: LoadError: LoadError: MethodError: no method matching var"@tm1"(::LineNumberNode, ::Module, ::Expr)
Closest candidates are:
  var"@tm1"(::LineNumberNode, ::Module, ::Any, ::Any) at /path/to/file.jl

```

But if I invoke the macro with an explicit string instead of `@ __DIR__ `, it works:

```julia
@tm1 "/tmp" begin
   3 + 3
end

```

All right, maybe macros don’t like taking another macro as an argument?

```julia
macro tm2(dir)
   :(begin
        println("tm2 dir: ", $dir)
     end)
end

@tm2 @ __DIR__

```

Which works fine! So a macro with _one_ parameter can take another macro as an argument, but with two (or more?) it breaks? WTF?

Julia version 1.6.2.

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [January 6, 2022, 5:31am UTC](https://discourse.julialang.org/t/macros-with-multiple-parameters/74120/2 "2022-01-06T05:31:35Z")

</div>

`@ __DIR__ ` needs to be in parentheses.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [January 6, 2022, 2:14pm UTC](https://discourse.julialang.org/t/macros-with-multiple-parameters/74120/3 "2022-01-06T14:14:52Z")

</div>

The problem is that when you write:

```julia
@a @b x

```

the parser treats that as calling macro `@b` with argument `x`, then calling macro `@a` with just one argument.

You can see that by using `dump` to look at the syntax tree:

```julia
julia> dump(:(@a @b x))
Expr
  head: Symbol macrocall
  args: Array{Any}((3,))
    1: Symbol @a
    2: LineNumberNode
      line: Int64 1
      file: Symbol REPL[5]
    3: Expr
      head: Symbol macrocall
      args: Array{Any}((3,))
        1: Symbol @b
        2: LineNumberNode
          line: Int64 1
          file: Symbol REPL[5]
        3: Symbol x

```

or just by constructing the expression and letting julia add some parentheses to disambiguate:

```julia
julia> :(@a @b x)
:(#= REPL[6]:1 =# @a #= REPL[6]:1 =# @b(x))

```

And you can fix this by adding the parentheses that you actually want instead:

```julia
julia> @tm1(@ __DIR__ (), begin
         3 + 3
       end)
tm1 dir: /home/user
6

```

In this case, it’s also sufficient to just add parens on the call to `@ __DIR__ ` to avoid it trying to grab the whole `begin` block as an argument:

```julia
julia> @tm1 @ __DIR__ () begin
         3 + 3
       end
tm1 dir: /home/user
6

```

---

<div class="post-metadata">

**Author:** ![gcv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gcv/32/11086_2.png) [@gcv](https://discourse.julialang.org/u/gcv)\
**Post date:** [January 6, 2022, 4:23pm UTC](https://discourse.julialang.org/t/macros-with-multiple-parameters/74120/4 "2022-01-06T16:23:14Z")

</div>

Thank you very much!
