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
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,
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
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:
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.
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.
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
how hygiene works in Julia,
how macros compose in Julia, and what happens to hygiene,
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.
You can, just put the whole quoted expression in esc.
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
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.
I think @ihnorton’s point is that macros are already beyond beginners’ proper 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.