===== Defining new macros =====
Disclamer:
A general rule of thumb is to try and not define new macros if they are not needed, or if they do not serve a specific purpose, since, while they do make the code more readable in some cases, they also make it way harder to debug the code.
==== Syntax ====
CL-USER> (defmacro name-of-macro (parameter list)
"Documentation"
(body of lisp expressions))
Macros are used to extend the syntax of standard LISP by generating/transforming code and adding new notations.
One important thing to note is that the computation of the body is already done at compile time and that it is possible to even quote LISP expressions, which enables us to generate code during compile-time.
For example:
CL-USER> (defmacro forty-two () (* 2 21))
CL-USER> 42
Calling (forty-two) now is equivalent to using 42.
CL-USER> (defmacro forty-two () '(* 2 21))
CL-USER> (* 2 21)
Now (forty-two) is equivalent to (* 2 21), which is evaluated to 42 during runtime.
=== Backquote/Comma ===
To make it easier to read/write complex expressions, we use backquotes (`) and commas (,) as follows:
CL-USER> (defmacro measure-time (type &body body)
"Macro to measure the time an action takes to finish, returns the returnvalue of the body"
`(let ((start (get-universal-time))
(value (progn ,@body)))
,(ccase type
(:start '(calculate-time start *total-time*))
(:init '(calculate-time start *total-init-time*))
(:movement '(calculate-time start *total-movement-time*))
(:manipulation '(calculate-time start *total-manipulation-time*))
(:detection '(calculate-time start *total-detection-time*)))
value))
The backquote (`) signals the start of an expression to LISP; inside of that expression, the comma (,) signals which subexpressions should be evaluated, while all other subexpressions are treated as if they are quoted (').
Note that in this example, we want the function calculate-time to be quoted in our code, since we told the macro to evaluate ccase during compile-time but want to evaluate calculate-time during runtime.