Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
tutorials:advanced:cram-macros [2022/04/10 23:15] lucatutorials:advanced:cram-macros [2022/04/10 23:34] (current) luca
Line 1: Line 1:
-===== Defining new macros =====+====== Defining new macros======
  
-Disclamer+Disclaimer
 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. 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.
  
-====== Defining new macros====== 
 ===== Syntax =====  ===== Syntax ===== 
  
Line 14: Line 13:
                                                        
 Macros are used to extend the syntax of standard LISP by generating/transforming code and adding new notations. 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. +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 through macro-expansion, which happens during compile-time. 
 For example: For example:
  
Line 59: Line 58:
 ===== Example of an CRAM-macro ===== ===== Example of an CRAM-macro =====
 <code lisp> <code lisp>
-(defmacro with-simulated-robot (&body body) +CL-USER> (defmacro with-simulated-robot (&body body) 
-  `(let ((results +          `(let ((results 
-           (proj:with-projection-environment urdf-bullet-projection-environment +                   (proj:with-projection-environment urdf-bullet-projection-environment 
-             (cpl-impl::named-top-level (:name :top-level) +                     (cpl-impl::named-top-level (:name :top-level) 
-               ,@body)))) +                       ,@body)))) 
-     (car (cram-projection::projection-environment-result-result results))))+             (car (cram-projection::projection-environment-result-result results))))
 </code> </code>
  
Line 75: Line 74:
  
 Here, "body" would now contain "(code that does awesome stuff)" Here, "body" would now contain "(code that does awesome stuff)"
-So now lets go through what the macro actually does. The first thing that is done, is to signal to LISP that an backquoted expression is about to start. In here, a variable "results" is created, which contains two nested, quoted functions/macros, aswell as our spliced, evaluated body. The endresult will look roughly like this:+So now let'go through what the macro actually does. The first thing that is done, is to signal to LISP that backquoted expression is about to start. Here, a variable "results" is created, which contains two nested, quoted functions/macros, as well as our spliced, evaluated body. The code contained by our variable "result" will look roughly like this:
  
 <code lisp> <code lisp>
Line 84: Line 83:
  
 Those two functions/macros will only be evaluated at runtime, as we can see from the quotes ('). Those two functions/macros will only be evaluated at runtime, as we can see from the quotes (').
 +After defining result, let's see roughly how the body of our macro will expand. Since non of the expressions have a comma (,) in front of them, every function/macro will be treated as if they were quoted ('):
 +
 +<code lisp>
 +'(car '(cram-projection::projection-environment-result-result ...))
 +</code>
 +
 +To conclude: without any prior knowledge of what the other functions/macros are doing we can tell, that this macro will try to evaluate the body as far as it can during macro expansion. The results will be passed onto other functions/macros, which are all evaluated during runtime, which makes sense, given that the macro name is "with-simulated-robot", which gives the impression that the code will be run while a robot is being simulated, which can obviously only happen during runtime, and not during macro expansion.