I’ve been playing a little more with macros and came up with a foreach-loop, similar to those used in Java or C#.
It basically does the same as the predefined dolist-macro, but oh well
foreach macro
1 2 3 4 5 6 7 8 9 10 | ;; foreach-loop, similar to those in Java or C# ;; example: (foreach (x '(1 2 3)) ;; (print x)) (defmacro foreach ((var list) &body body) `(let ((,var (car ,list)) (rest (cdr ,list))) (if ,var (progn ,@body (foreach (,var rest) ,@body)) nil))) |
I’ve also come up with my own file-handling macro, similar to the predefined with-open-file:
with-file macro
1 2 3 4 5 | ;; can be used like with-open-file macro (defmacro with-file ((filestream-var filename &optional &key (if-exists nil) (direction :input)) &body body) `(let ((,filestream-var (open ,filename :direction ,direction :if-exists ,if-exists))) ,@body (close ,filestream-var))) |
At first macros seemed to be something complicated, but once I’ve started reimplementing some of the standard macros and also making up my own custom ones, it really got much clearer to me how they work and why they are so important. Especially the with-file macro gives you an idea of whats possible with macros. Abstracting away the pattern of opening a file, doing something and then closing it again is just really nice, since you won’t ever forget to close it again, if you stick with using the macro.
I’ll try to come up with some more soon.
Next big thing on my agenda is some file in- and output as well as CLOS, the powerful Common Lisps Object System.


4 Responses
Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.
The for each macro does not work. Try to use it in a function and compile that file. It only works for literal lists in an interpreter mode that does not expand the code completely before executing it. The macro calls itself and dies in recursion.
You should not use ,list multiple times in the macro.
thanks for the advise.
i wrote these macros while still using clisp and it seemed to work, but you’re right in that they only work when in interpreted mode.
i’ve found a better way to do this via tagbody & go… i’ll probably post them here too.
Well, they won’t work in a) implementations that use only a compiler (there are several) or use some interpreter variant, where code gets expanded fully before executed.
You don’t really want to use tagbody in your code.
i know it’s messy. any other solution how to do it, without using standard looping macros?