Hm. Here is an example of such a macro in general lisp. Note, however, that I'm not sure if this is actually a good idea. But we are all adults here, right?
(defmacro nested-loop (control &body body) (let ((variables ()) (lower-bounds ()) (upper-bounds ())) (loop :for ctl :in (reverse control) :do (destructuring-bind (variable bound1 &optional (bound2 nil got-bound2)) ctl (push variable variables) (push (if got-bound2 bound1 0) lower-bounds) (push (if got-bound2 bound2 bound1) upper-bounds))) (labels ((recurr (vars lowers uppers) (if (null vars) `(progn ,@body) `(loop :for ,(car vars) :upfrom ,(car lowers) :to ,(car uppers) :do ,(recurr (cdr vars) (cdr lowers) (cdr uppers)))))) (recurr variables lower-bounds upper-bounds))))
The syntax is slightly different from your suggestion.
(nested-loop ((i 0 10) (j 15) (k 15 20)) (format t "~D ~D ~D~%" ijk))
expands in
(loop :for i :upfrom 0 :to 10 :do (loop :for j :upfrom 0 :to 15 :do (loop :for k :upfrom 15 :to 20 :do (progn (format t "~d ~d ~d~%" ijk)))))
The first argument to the macro is a list of the form list.
(variable upper-bound)
(with a lower limit of 0 implied) or
(variable lower-bound upper-bounds)
With less love applied, you can even something like
(nested-loop ((i :upfrom 10 :below 20) (j :downfrom 100 :to 1)) ...)
but then, why bother if the loop already has all these functions?
Dirk
source share