The DO-LOOP Macro
The do-loop
and loop*
macro family are essentially just loop
with added features to make them similar in capabilities to the with-bindings
macro family described in #4. loop*
is essentially just an extended cl:loop
, while do-loop
breaks each clause up into s-expressions.
For instance, iota
could be defined as:
(defun iota (n)
(loop :for i :from 0 :below n
:collect i))
The implementation using loop*
would be identical to the above (substituting loop*
in the place of loop
) because this example doesn't use anything where loop*
's features differ from loop
, making it much easier to learn than similar iteration macros. Some differences would include powerful destructuring (as opposed to loop
's extremely basic destructuring), nonconsing multiple value binding, etc., and potentially even the ability to extend loop*
to learn new ways to bind and iterate.
Using do-loop
, iota
can be defined as:
(defun iota (n)
(do-loop (:for i :from 0 :below n)
(:collect i)))
Again, it is very easy to learn because there is essentially no difference in most use cases except for the advantage of having an s-expression structure rather than relying on a grammar.
Some uses of loop
would be invalid in do-loop
because do-loop
would work by having a plist tail, thus not allowing clauses like :being :the
. As a plist, it would probably require keywords (except perhaps for the first symbol in a form?) instead of permitting symbols in any package. On the other hand, using plists means that the order is flexible.
Notice, however, that these macros are essentially just enhanced loop
variations so anyone who knows how to use loop
(which should be almost any Common Lisper) should be able to pick up these two macros very quickly, which is one of the reasons why these macros are planned rather than just suggesting the use of a preexisting iteration macro. (Some are quite close to do-loop
but use extra parentheses over than the small number of parentheses that do-loop
adds. do-loop
is intended to be essentially the smallest number of parentheses required to replace almost all of the ,@
s in your iteration-generating macros with ,
s.) The other reason is for integration with the with-bindings
and define-function
macro families.
These macros will probably need special indentation support in GNU Emacs.