Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use macros in Julia?

Tags:

julia

I was reading up on the documentation of macros and ran into the following under the `Hold up: why macros' section. The reasoning given to use macros is as follows:

Macros are necessary because they execute when code is parsed, therefore, macros allow the programmer to generate and include fragments of customized code before the full program is run

This leads me to wonder why someone would want to use "generate and include fragments of customized code before the full program is run". Can someone provide context as to why this would be beneficial and/or other good use cases for macros?

like image 877
logankilpatrick Avatar asked Feb 04 '23 17:02

logankilpatrick


1 Answers

Let me give you my view on macros.

A macro basically is a code -> code function. It takes code (a Julia expression) as input and spits out code (a different Julia expression).

Why is this useful? It has multiple purposes:

  • compile time copy-and-paste: You don't have to write the same piece of code multiple times but instead can define a short macro that writes it for you wherever you put it. (example)

  • domain specific language (DSL): You can create special syntax that after the macros code -> code transform is replaced by pure Julia constructs. This is used in many packages to define special syntax, for example here and here.

  • code generation: Imagine you want to write a really long piece of code which, although being long, is very simple because it has some kind of pattern that repeats itself rather trivially. Writing that code by hand can be a pain (or even practically impossible). A macro can programmatically generate the code for you. One example is for-loop unrolling (see here and here). But even the @time macro isn't doing much more than just putting a bunch of Base.time_ns() function calls around the provided Julia expression.

  • special string parsing: If you type the literal 3.2 in Julia it will be parsed and interpreted as a Float64. Now, imagine you want to supply a number literally that goes beyond Float64 precision but would fit into a BigFloat. Typing big(3.123124812498124812498) won't work, because the literal number is first interpreted as a Float64 and then handed to the big function. Instead you need a way to tell Julia at parse time that this should become a BigFloat. This is handled by a @big_str 3.2 macro which (for convenience) can also be written as big"3.2". The latter is just syntactic sugar.

There might be many more applications of macros, but those are the most important to me.

Let me end by referencing Steven G. Johnson's great talk at JuliaCon 2019:

Most of the time, don't do metaprogramming :)

like image 80
carstenbauer Avatar answered Feb 12 '23 23:02

carstenbauer