My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
doplus  

Featured
Updated Apr 7, 2012 by alessios...@gmail.com

doplus - simple, high-level, extensible iteration construct

doplus (written DO+) is an iteration macro for Common Lisp. I wrote it because:

  • I want to code in Lisp, not in Pascal (LOOP, I'm looking at you!)
  • Code-walkers are evil and simple iteration should not require one (iterate suffers from this problem).

The code for doplus is here.

Table of contents

Overview and main features

doplus basically can be thought as a high-level DSL over CL:DO [*]. In spirit it's similar to iterate, but having implementation simplicity as a core goal, the syntax is necessarily a bit different to accomodate the lack of a code walker that can freely move pieces of code around. Also, doplus generally requires the user to be a bit more explicit than both LOOP and iterate.

doplus, like iterate, is meant to be extensible by simply writing macros. By contrast, LOOP is not portably extensible, and on those implementations where it is, it's not trivial to extend it. Most macros that extend doplus can be written combining built-in operators and producing code in doplus syntax, just like a user might have written it. This makes many possible doplus extensions very readable.

doplus is fully understood by SLIME, since it uses regular macros and defines dummy top-level macros for its body-local macrolets, to make symbol completion available for them as well.

doplus is, to my knowledge, the only advanced iteration construct in Lisp to support atomic initialization and stepping of iteration variables. Refer to the manual section Initialization and stepping for more information.

[*] doplus used to be actually written on top of cl:do*, but has been rewritten using lower-level constructs to have more control on the various steps of iteration.

Status

I now consider doplus to be quite mature. I've been using it exclusively in my own projects, and it's been on Quicklisp since late 2011.

Initially, it progressed very quickly from idea to unfinished hack to something that could be used in real code. It has then been used and refined by the author with the invaluable aid of other Lispers, most notably Tamas K. Papp. Nowadays it provides most of LOOP's and iterate's features, either built-in or easy to emulate, and it has its own unique features.

The big, scary example

In all its glory:

 CL-USER>
 (do+ ((for x (in '(1 3 5 7 9)))
       (for k (from 10 :to 0))
       (initially (format t "initially k = ~S~%" k))
       (for m (to 100 :by 5))
       (initially (format t "another init form~%"))
       (with (y 42) z)
       (stop-when (eql x 7))
       (counting loops)
       (finally (format t "finally k = ~S~%" k))
       (accumulating-to w)
       (accumulating-to p :initially 0 :by #'+ :finally #'-)
       (returning (list 'x x 'y y 'z z 'k k 'm m 'w w 'p p
                        'loops loops 'max-length max-length 'longest-list longest-list))
       (finally (format t "another final form~%"))
       (finding max-x (maximizing x))
       (for list (in '((1 2) (3) (4 5 6) (7 8) (9))))
       (finding max-length (maximizing (length list) :saving list :in longest-list)))
   (let ((foo "look ma, body is nested!"))
     (declare (ignore foo))
     (format t "~%loop n° ~A~%" loops)
     (format t "before collect, x ~A y ~A z ~A k ~A m ~A w ~A ~% list ~A max-length ~A longest-list ~A ~%"
             x y z k m w list max-length longest-list)
     (collect x :into w)
     (collect x :into p)
     (format t "after collect, x ~A y ~A z ~A k ~A m ~A w ~A ~% list ~A max-length ~A longest-list ~A ~%"
             x y z k m w list max-length longest-list)))
 initially k = 10
 another init form
 

loop n° 0 before collect, x 1 y 42 z NIL k 10 m 0 w NIL list (1 2) max-length 2 longest-list (1 2) after collect, x 1 y 42 z NIL k 10 m 0 w (1) list (1 2) max-length 2 longest-list (1 2)

loop n° 1 before collect, x 3 y 42 z NIL k 9 m 5 w (1) list (3) max-length 2 longest-list (1 2) after collect, x 3 y 42 z NIL k 9 m 5 w (3 1) list (3) max-length 2 longest-list (1 2)

loop n° 2 before collect, x 5 y 42 z NIL k 8 m 10 w (3 1) list (4 5 6) max-length 2 longest-list (1 2) after collect, x 5 y 42 z NIL k 8 m 10 w (5 3 1) list (4 5 6) max-length 2 longest-list (1 2) finally k = 7 another final form (X 7 Y 42 Z NIL K 7 M 15 W (1 3 5) P -9 LOOPS 3 MAX-LENGTH 3 LONGEST-LIST (4 5 6))

This covers many, but not all, of the features do+ has.

Manual

The manual is on a separate page.


Sign in to add a comment
Powered by Google Project Hosting