# How can Julia macro take an Expr variable as its arguments?

**URL:** https://discourse.julialang.org/t/how-can-julia-macro-take-an-expr-variable-as-its-arguments/82630
**Category:** New to Julia
**Created:** [June 12, 2022, 11:21am UTC](https://discourse.julialang.org/t/how-can-julia-macro-take-an-expr-variable-as-its-arguments/82630 "2022-06-12T11:21:19Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Brian1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brian1/32/49250_2.png) [@Brian1](https://discourse.julialang.org/u/Brian1)
#### Post date: [June 12, 2022, 11:21am UTC](https://discourse.julialang.org/t/how-can-julia-macro-take-an-expr-variable-as-its-arguments/82630/1 "2022-06-12T11:21:19Z")

</div>

Here is a simple macro

```julia
macro pre_print(expr::Expr)
    println("show....")
    return quote
        $expr
    end
end

```

I can use it as:

```julia
@pre_print a=10

#show....

#10

```

But how can this macro take an expr as its argument, like:

```julia
test_expr = :(a=10)

@pre_print(test_expr)

LoadError: MethodError: no method matching var"@pre_print"(::LineNumberNode, ::Module, ::Symbol)
Closest candidates are:
  var"@pre_print"(::LineNumberNode, ::Module, ::Expr) at In[7]:1
in expression starting at In[11]:1

Stacktrace:
 [1] eval
   @ .\boot.jl:368 [inlined]
 [2] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
   @ Base .\loading.jl:1281

```

---

<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 12, 2022, 11:36am UTC](https://discourse.julialang.org/t/how-can-julia-macro-take-an-expr-variable-as-its-arguments/82630/2 "2022-06-12T11:36:29Z")

</div>

> [@Brian1](#):
>
> But how can this macro take an expr as its argument, like:
> 
> ```julia
> test_expr = :(a=10)
> 
> @pre_print(test_expr)
> 
> ```

A macro does not see the value of a variable (`test_expr` in this case), only the code that is immediately written in its parsed block. At the time of macro expansion, that variable does not yet have a value (even in global scope, should the variable have a value - the macro does not see it) - it can only see the symbol you’ve written in the literal expression block inside of those `()`.

A macro is distinct from a function that takes an `Expr` object.

---

<div class="post-metadata">

### Author: ![Brian1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brian1/32/49250_2.png) [@Brian1](https://discourse.julialang.org/u/Brian1)
#### Post date: [June 13, 2022, 5:06pm UTC](https://discourse.julialang.org/t/how-can-julia-macro-take-an-expr-variable-as-its-arguments/82630/3 "2022-06-13T17:06:41Z")

</div>

Thanks for your help. In some situation, maybe it is not a proper way to use macro.

---

<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 13, 2022, 8:45pm UTC](https://discourse.julialang.org/t/how-can-julia-macro-take-an-expr-variable-as-its-arguments/82630/4 "2022-06-13T20:45:54Z")

</div>

You can think of it this way. The macro definition you write takes in an expression and returns an expression, much like a method can. But only a method could take in a runtime `Expr` instance and return another. The macro definition is just a way for you to customize one part of a bigger process of parsing and evaluating _source code_. You can’t control the parser converting the source code to an `Expr` that the macro will work on, and you can’t control the macro’s output `Expr` being evaluated. (You can however use `@macroexpand` to wrap the output `Expr` in an extra `Expr` layer so when it is evaluated, you get the output `Expr`.)

This incidentally is why macros are said to only work on literals, symbols, and `Expr` of such; it’s because the _parser_ can only produce such things from source code. However, there is actually an internal (not public API, not stable across versions) [trick](https://discourse.julialang.org/t/is-there-a-trick-to-input-an-expr-into-a-macro/82383/5) to get the macro definition’s underlying method, which _can_ take in runtime `Expr` instances. Right after that trick’s comment in the thread, I also commented how to use the wholly public `macroexpand` function and `$`-interpolation to make a macro work on a runtime `Expr`.
