Earlier quoted context omitted.
Yesterday I was writing code that kept messing my Lisp's signal handling, so I wrote a FOR-DURATION macro that arms a timeout and makes sure whatever that runs in its body gets killed after N seconds. Here it is: (defmacro for-duration ((seconds) &body body) `(handler-case (bt:with-timeout (,seconds) ,@body) (bt:timeout () nil))) Five lines to alter the evaluation model of your language. Not bad. Use as: (for-duratio…
C99 + GCC extensions + POSIX: #define for_duration(seconds, body) \ { \ pthread_t tid_task, tid_watcher; \ \ void* task(void* arg) { \ body ; \ pthread_cancel(tid_watcher); \ return NULL; \ } \ \ void* watcher(void* arg) { \ sleep((seconds)); \ pthread_cancel(tid_task); \ return NULL; \ } \ \ pthread_create(&tid_task, NULL, &task, NULL); \ pthread_create(&tid_watcher, NULL, &watcher, NULL); \ pthread_join(tid_task, N…
(defmacro execute-in-reverse (&body body)
`(progn ,@(reverse body)))
(execute-in-reverse (print "Hi") (print "Middle") (print "Bye"))
Prints... "Bye"
"Middle"
"Hi"
Point: You can do whatever you want with the symbols sent to the macro, whatever their contents. Mahmud's wrapper macro is trivial (it could be done with lambdas). Lisp's macro system allows you to create new syntax, including changes in flow control.But my example is trivial, too. I could go on to swap individual parts of my forms around, remap them to other forms depending on various conditions, etc.
In addition, people often talk about Lisp macros, but they neglect to mention the power of reader macros, which allow you to go beyond Lisp's basic AST look-and-feel.