# Looking for good macro examples

**URL:** <https://discourse.julialang.org/t/looking-for-good-macro-examples/450>\
**Category:** General Usage\
**Tags:** question\
**Created:** [November 20, 2016, 1:29pm UTC](https://discourse.julialang.org/t/looking-for-good-macro-examples/450 "2016-11-20T13:29:29Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 20, 2016, 1:29pm UTC](https://discourse.julialang.org/t/looking-for-good-macro-examples/450/1 "2016-11-20T13:29:29Z")

</div>

I still develop my Julia macros by trial and error, and since they are a bit different from Common Lisp macros, I am realizing that I need to learn a different way for idiomatic usage. The principle is the same as in CL, but hygiene is implemented differently, and there are subtle issues (like no equivalent for `&body` macros, eg one could not reimplement `for` or `if` with macros if they weren’t part of the language). Nevertheless, I am convinced that Julia macros are powerful, I just need to learn the right way to use them.

I am wondering if I could get

1. Recommendations for **examples** which I could study to learn about good practices and elegant use of macros, eg in some package code that uses macros elegantly,
2. Pointers for **open issues and corner cases** which I should watch out for.

I have read the manual, but it is of course just a short introduction of concepts. Feel free to push your own packages/blog posts 🙂

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [November 20, 2016, 2:04pm UTC](https://discourse.julialang.org/t/looking-for-good-macro-examples/450/2 "2016-11-20T14:04:34Z")

</div>

Writing a macro is: (1) take AST apart, (2) do something with the pieces, and (3) put modified pieces back together".

Constructing a AST (step 3) is (usually) quite easy with quote-blocks and interpolation. However, deconstructing a AST (step 1) is a quite a tedious exercise in dissecting nested datastructures. Enter MacroTools.jl which gives you a DSL to do this:

> **[GitHub - FluxML/MacroTools.jl: MacroTools provides a library of tools for...](https://github.com/FluxML/MacroTools.jl)**
>
> MacroTools provides a library of tools for working with Julia code and expressions. - GitHub - FluxML/MacroTools.jl: MacroTools provides a library of tools for working with Julia code and expressions.

I do macro-batics in my packages [GitHub - mauro3/SimpleTraits.jl: Simple Traits for Julia](https://github.com/mauro3/SimpleTraits.jl) (uses MacroTools) and [GitHub - mauro3/Parameters.jl: Types with default field values, keyword constructors and (un-)pack macros](https://github.com/mauro3/Parameters.jl), but they are probably not the best examples.

Regarding hygiene, have a look at [RFC: WIP: Make macro hygiene easier to use and less error-prone by vtjnash · Pull Request #10940 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/10940) and [https://github.com/JuliaLang/julia/pull/6910](https://github.com/JuliaLang/julia/pull/6910).

---

<div class="post-metadata">

**Author:** ![ihnorton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihnorton/32/26_2.png) [@ihnorton](https://discourse.julialang.org/u/ihnorton)\
**Post date:** [November 20, 2016, 5:53pm UTC](https://discourse.julialang.org/t/looking-for-good-macro-examples/450/3 "2016-11-20T17:53:49Z")

</div>

I think it is unwise to recommend MacroTools for non-expert use. It adds an extra layer of inscrutability on top of meta-programming concepts that many people already have trouble understanding.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [November 20, 2016, 6:26pm UTC](https://discourse.julialang.org/t/looking-for-good-macro-examples/450/4 "2016-11-20T18:26:34Z")

</div>

True, although the OP seems to have experience from Lisp.

Also, by the same token: should one recommend to non-experts to construct the AST by piecing the `Expr` together by hand instead of using `quote` and interpolation? Answer: Probably, until the novice understands that meta-programming is nothing magical but instead just manipulation of a nested datastructure.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 20, 2016, 6:36pm UTC](https://discourse.julialang.org/t/looking-for-good-macro-examples/450/5 "2016-11-20T18:36:54Z")

</div>

I find MacroTools.jl a promising start: in general it is my impression that destructuring/unification needs more libraries in Julia, especially for metaprogramming.

Until I understand more about Julia’s macros, I am wary of using it because I don’t yet have a good mental model of

1. how hygiene works in Julia,
2. how macros compose in Julia, and what happens to hygiene,
3. macros that write macros in Julia.  
I will undoubtedly learn about 1–2 by reading examples, and making mistakes, but there seems to be very little of 3 at the moment.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [November 20, 2016, 7:03pm UTC](https://discourse.julialang.org/t/looking-for-good-macro-examples/450/6 "2016-11-20T19:03:53Z")

</div>

> [@Tamas\_Papp](#):
>
> 1. macros that write macros in Julia.

See for an example:

> <https://github.com/mauro3/Parameters.jl/blob/546c5341706151b44c99e370a190814a264fb3ab/src/Parameters.jl#L398>

Although, I’m not sure I handle hygiene in the most elegant way. (Edit: In fact, I’m pretty sure I don’t)

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [November 20, 2016, 11:58pm UTC](https://discourse.julialang.org/t/looking-for-good-macro-examples/450/7 "2016-11-20T23:58:47Z")

</div>

Writing macros became a lot more pleasant for me when I gave up on hygiene. Just use gensyms, and prefix every function call with `$ModuleName.`

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 21, 2016, 7:26am UTC](https://discourse.julialang.org/t/looking-for-good-macro-examples/450/8 "2016-11-21T07:26:58Z")

</div>

@cstjean: but you still need to `esc` expressions from the arguments, don’t you? I wish I could turn the whole hygiene mechanism off somehow.

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [November 21, 2016, 12:38pm UTC](https://discourse.julialang.org/t/looking-for-good-macro-examples/450/9 "2016-11-21T12:38:20Z")

</div>

> [@Tamas\_Papp](#):
>
> I wish I could turn the whole hygiene mechanism off somehow.

You can, just put the whole quoted expression in `esc`.

```julia
module MM
foo(y) = println("foo was called with $y")
macro foo_fun(name, expr)
    x = gensym()
    esc(quote
        function $name($x)
            $MM.foo($x)
            $expr
        end
    end)
end
end

using MM: @foo_fun
@foo_fun bobby 45
bobby(4)

```

I haven’t written any macro-writing-macro yet, I’m not sure how that goes. Julia’s `quote` is a backquote, but you can get normal-quote by writing

```julia
y = :u
quote
    $(Expr(:quote, y))
end

```

It’s equivalent to `',` in Common Lisp.

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [November 21, 2016, 12:51pm UTC](https://discourse.julialang.org/t/looking-for-good-macro-examples/450/10 "2016-11-21T12:51:54Z")

</div>

As for `&body`, you can get something similar through

```julia
macro my_for(do_body, list)
    :(foreach($do_body, $list))
end

@my_for([1,2,3]) do x
    println(x+2)
end

```

`do_body` is an `Expr` that you could destructure.

---

<div class="post-metadata">

**Author:** ![MikeInnes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikeinnes/32/3656_2.png) [@MikeInnes](https://discourse.julialang.org/u/MikeInnes)\
**Post date:** [November 21, 2016, 1:25pm UTC](https://discourse.julialang.org/t/looking-for-good-macro-examples/450/11 "2016-11-21T13:25:42Z")

</div>

You could argue that the MacroTools readme tries to introduce too much too early, but the basic case looks like:

```julia
ex = :(foo(x, y) = x*y)

@capture(ex, f_(args__) = body_)

(f, args, body) == (:foo, [:x, :y], :(x*y))

```

This is perfectly analogous to construction via syntax (`quote`, `:(...)`) so I’m not sure why it should be any more inscrutable or complex; if you can understand one you can understand the other. Like any abstraction it can be leaky, but that doesn’t mean you can’t learn in the abstract and get lower-level as necessary.

Of course, I definitely don’t recommend that beginners try to do more advanced stuff like expression-walking straight away.

---

<div class="post-metadata">

**Author:** ![akis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/akis/32/156_2.png) [@akis](https://discourse.julialang.org/u/akis)\
**Post date:** [November 21, 2016, 7:38pm UTC](https://discourse.julialang.org/t/looking-for-good-macro-examples/450/12 "2016-11-21T19:38:29Z")

</div>

> [@MikeInnes](#):
>
> Of course, I definitely don’t recommend that beginners try to do more advanced stuff like expression-walking straight away.

I think @ihnorton’s point is that macros are **already** beyond beginners’ proper understanding:

> [@ihnorton](#):
>
> many people already have trouble understanding

They may be able to copy an example and adapt it in their code to the point of not raising errors, but they cannot say if that actually worsens their code instead of improving it. An extra warning shouldn’t harm.
