#MonthOfJulia Day 11: Metaprogramming
Metaprogramming in Julia is a big topic and it’s covered extensively in both the official documentation as well as in the Introducing Julia wikibook. The idea behind metaprogramming is to write code which itself will either generate or change other code. There are two main features of the language which support this idea:
- code representation (expressions and symbols) and
A symbol (data type
Symbol) represents an unevaluated chunk of code. As such, symbols are a means to refer to a variable (or expression) itself rather than the value it contains.
The quote operator,
:, prevents the evaluation of its argument.
Expressions are made up of three parts: the operation (
head), the arguments to that operation (
args) and finally the return type from the expression (
We can evaluate an expression using
eval(). Not only does
eval() return the result of the evaluated expression but it also applies any side effects from the expression (for example, variable assignment).
No real surprises there. But the true potential of all this lies in the fact that the code itself has an internal representation which can be manipulated. For example, we could change the arguments of the expression created above.
That still seems a little tame. What about manipulating a function?
Macros are a little like functions in that they accept arguments and return a result. However they are different because they are evaluated at parse time and return an unevaluated expression.
macroexpand() is used to look at the code generated by the macro. Note that parentheses were automatically inserted to ensure the correct order of operations.
Julia has a plethora of predefined macros which do things like return the execution time for an expression (
@time), apply an assertion (
@assert), test approximate equality (
@test_approx_eq) and execute code only in a UNIX environment (
The fact that one can use code to build and edit other code made me start thinking about self-replicating machines, self-reconfiguring modular robots, grey goo and utility fog. If we can do it in software, why not in hardware too? More evidence of my tinkering with metaprogramming in Julia can be found on github. No self-reconfiguring modular robots though, I’m afraid.