# Macro question (create variables)

**URL:** https://discourse.julialang.org/t/macro-question-create-variables/90160
**Category:** General Usage
**Tags:** macros, metaprogramming
**Created:** [November 12, 2022, 11:35am UTC](https://discourse.julialang.org/t/macro-question-create-variables/90160 "2022-11-12T11:35:19Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [November 12, 2022, 11:35am UTC](https://discourse.julialang.org/t/macro-question-create-variables/90160/1 "2022-11-12T11:35:19Z")

</div>

Wanted: a macro

```julia
@moo a b

```

which is in effect equivalent to

```julia
a = foo("a")
b = foo("b")

```

and actually I got it:

```julia
foo(x) = "$x-$x" 

macro moo(args...)
    for x in args
        xs = string(x)
        @eval eval(Meta.parse("$($xs) = foo(\"$($xs)\")"))
    end
end

@moo v1 v2
@show v1 v2 ;

julia> 

v1 = "v1-v1"
v2 = "v2-v2"

```

However `@eval eval(Meta.parse(` looks ugly to me, there is probably a more proper way to achieve the result.

---

<div class="post-metadata">

### Author: ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)
#### Post date: [November 12, 2022, 1:00pm UTC](https://discourse.julialang.org/t/macro-question-create-variables/90160/2 "2022-11-12T13:00:16Z")

</div>

Don’t use `eval` within a macro. A macro is a function that get’s a parsed, yet unevaluated, expression as input and can transform it into another expression which is to be executed instead.  
More concretely, let’s write `@moo` with a single variable as input:

1. What input does `@moo` get when called as `@moo a`?

```julia
julia> expr = Meta.parse("a") # argument expression after being parsed
:a

julia> typeof(expr)
Symbol

julia> dump(expr) # expression, i.e., input to @moo will just be a symbol
Symbol a

```

From this symbol, we now want to construct a more complicated expression which contains the literal symbol as well as its name as a string

```julia
julia> res_expr = Meta.parse("a = foo(\"a\")")
:(a = foo("a")) # desired output of @moo a

julia> dump(res_expr)
Expr
  head: Symbol =
  args: Array{Any}((2,))
    1: Symbol a
    2: Expr
      head: Symbol call
      args: Array{Any}((2,))
        1: Symbol foo
        2: String "a"

```

Now, the macro is a pure function which takes the symbol as input and produces the desired expression as output:

```julia
julia> macro moo(var)
           # Return expression with symbol interpolated literally on the lhs and as a string on the rhs
           :($(esc(var)) = foo($(string(var))))
       end
@moo (macro with 1 method)

julia> @macroexpand @moo a # Macro indeed transforms the given symbol into the desired expression
:(a = Main.foo("a"))

```

Be sure to also read the [Metaprogramming](https://docs.julialang.org/en/v1/manual/metaprogramming/) chapter from the Julia manual. Other good sources to understand macros in general, i.e., not just in Julia, are [On Lisp](http://www.paulgraham.com/onlisp.html) or [Practical Common Lisp](https://gigamonkeys.com/book/).

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [November 12, 2022, 8:51pm UTC](https://discourse.julialang.org/t/macro-question-create-variables/90160/3 "2022-11-12T20:51:45Z")

</div>

[bertschi](https://discourse.julialang.org/u/bertschi) thank you for the detailed explanation.

After some searching (specifically [this](https://discourse.julialang.org/t/can-i-concatenate-expressions-in-macro/69220/5) and [this](https://discourse.julialang.org/t/how-does-julia-merge-several-exprs-to-one-expr/77498/4) topics were useful) and some experimenting I got solution for multiple arguments:

```julia
foo(x) = "$x-$x" 

macro moo2(args...) 
    v = [:($x = foo($(string(x)))) for x in args]
    return esc(Expr(:block, v...))
end

@moo2 w1 w2
@show w1 w2;

julia> 

w1 = "w1-w1"
w2 = "w2-w2"

```

Now, can anybody explain me why do I need this `esc` here in the `return` statement?

---

<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: [November 12, 2022, 9:05pm UTC](https://discourse.julialang.org/t/macro-question-create-variables/90160/4 "2022-11-12T21:05:03Z")

</div>

> [@Eben60](#):
>
> Now, can anybody explain me why do I need this `esc` here in the `return` statement?

This comes down to what we call “macro hygeine”. There’s a section in the documentation here: [Metaprogramming · The Julia Language](https://docs.julialang.org/en/v1/manual/metaprogramming/#Hygiene)

The basic idea is that if you write something like

```julia
macro foo(ex)
    quote
        x = 1
        y = x + $ex
     end
end 

```

it would be very bad and surprising if the variables referred to there affected code outside of the macro unless you specifically intend it to. E.g. consider this:

```julia
function f(x)
    @foo x
    x
end

```

Without macro hygiene, `f(2)` would return `1`, which might be very surprising. So instead what happens is this:

```julia
julia> @macroexpand @foo ex
quote
    #= REPL[17]:3 =#
    var"#59#x" = 1
    #= REPL[17]:4 =#
    var"#60#y" = var"#59#x" + Main.ex
end

```

So the intermediate variables here aren’t actually named `x` or `y`, they get names that are guaranteed to not clash with surrounding code.

However, sometimes you don’t want this, especialy if you need to actually return and evaluate code that a user passed into the macro. So when you write `esc(expr)`, that essentially is a marker saying "I want everything inside `expr` to not be made hygenic.

---

<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: [November 12, 2022, 9:09pm UTC](https://discourse.julialang.org/t/macro-question-create-variables/90160/5 "2022-11-12T21:09:44Z")

</div>

The best practice is to only apply `esc` to specific parts of the returned expression which need it. So in your case, I would write your macro as

```julia
macro moo3(args...) 
    v = [:($(esc(x)) = foo($(string(x)))) for x in args]
    return Expr(:block, v...)
end

```

because then `foo` does not get escaped.

Here’s a demonstraction of why:

```julia
julia> let 
           foo(x) = x #some user locally redefines `foo(x)`
           @moo2 w1 w2
           w1, w2
       end 
("w1", "w2") 

```

uh-oh, this isn’t the output we intended!

Now look at how `@moo3` deals with this:

```julia
julia> let 
           foo(x) = x
           @moo3 w1 w2
           w1, w2
       end
("w1-w1", "w2-w2")

```
