How to use macros for testing in Julia
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.
Defining a macro
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.
Invoking a macro
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.
Code example 1
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")
Code explanation
Let's go through the code widget above:
Line 1: We define a macro named
macro1that takes one argument calledp1.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
macro1macro previously declared.
Code example 2
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
Code explanation
Let's go over the code widget above:
Line 1: We define a macro named
verifythat accepts one argument calledex.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
exprovided as an argument, if true, then do nothing otherwise, throw an error.Lines 7–12: We invoke the
verifymacro while specifying the expression1*1 = 1as an argument to test whether this expression is valid or not.Lines 14–19: We invoke the
verifymacro while specifying the expression1 + 3 == 3as an argument to check whether this expression is valid or not.Lines 21–26: We call the
verifymacro while specifying the expression2*1 == 1as an argument to ascertain the validity of this expression.
Free Resources