In Julia's ecosystem, expressions and macros foster the metaprogramming paradigm. The macro concept can be considered a function for creating and evaluating expressions. Macros can be used to transform programs in a customized manner.
With macros, we can insert custom code during parsing and then execute that code during program execution.
To define a macro, we need to use the keyword macro
as shown below:
macro name(args) Unevaluated Input Expression –> Output Expression
The args
represents the input expression arguments which can take the form of symbols, other expressions, or literals.We can explore these arguments by calling the show()
function within the body of the macro. The Unevaluated Input Expression
is an expression in an unevaluated form, and the Output Expression
is the resulting compiled expression.
Below is the syntax to invoke a macro:
@name(args) or @name args
When debugging, we often want to know what expression the macro is evaluating without executing it. The following macroexpand
method is used:
@macroexpand @name(args) or @macroexpand @name args
Let's take a look at the macros functioning below.
This basic example illustrates how to define and call a macro:
macro macro1(p1)show(p1)return :( println("\nMy macro input parameter is:" , $p1) )end@macro1("123")
Let's go through the code widget above:
Line 1: We define a macro named macro1
that takes one argument called p1
.
Line 2: We display the value of the specified argument p1
.
Line 3: We refer to the expression to be evaluated and returned by the macro.
Line 5: We invoke the macro1
macro previously declared.
The example below shows how a macro can be expanded to evaluate an expression specified as a parameter for testing purposes. Basically, It accepts an expression as a parameter and tests whether it is valid or not.
macro verify(ex)print("\nVerifiying Expression ")show(ex)return :( $ex ? nothing : throw(AssertionError($(string(ex)))) )endtry@verify 1*1 == 1print("\nExpression is valid ")catch eprintln("\n",e)endtry@verify 1+3 == 3print("\nExpression is valid ")catch eprintln("\n",e)endtry@verify 2*1 == 1print("\nExpression is valid ")catch eprintln("\n",e)end
Let's go over the code widget above:
Line 1: We define a macro named verify
that accepts one argument called ex
.
Line 2: We print out an informative message.
Line 3: We display the value of the specified argument ex
.
Line 4: We evaluate the expression ex
provided as an argument, if true, then do nothing otherwise, throw an error.
Lines 7–12: We invoke the verify
macro while specifying the expression 1*1 = 1
as an argument to test whether this expression is valid or not.
Lines 14–19: We invoke the verify
macro while specifying the expression 1 + 3 == 3
as an argument to check whether this expression is valid or not.
Lines 21–26: We call the verify
macro while specifying the expression 2*1 == 1
as an argument to ascertain the validity of this expression.
Free Resources