Or see the list of project sponsors.
Do+ is a macro, similar to 'loop' or 'iterate', but built with simplicity in mind.
Documentation is good and contains some examples showing how iteration works as well as how to extend do+ with new iteration methods.
Here is a simple iteration on the list:
POFTHEDAY> (use-package :doplus)
T
POFTHEDAY> (do+
(for i (in "Hello world!"))
(collect i))
(#\H #\e #\l #\l #\o #\ #\w #\o #\r #\l #\d #\!)
Let's try to extend do+ to iterate on week days by using the defclause macro:
POFTHEDAY> (defclause in-days ()
`(for ,*iteration-variable*
(in '(:monday :tuesday :wednesday
:thursday :friday :saturday :sunday))))
POFTHEDAY> (do+
(for day (in-days))
(format t "Hello ~A~%" day))
Hello MONDAY
Hello TUESDAY
Hello WEDNESDAY
Hello THURSDAY
Hello FRIDAY
Hello SATURDAY
Hello SUNDAY
Another cool feature is support for generators. BTW, :iterate supports them too.
Let's try to build a generator which emits an infinite sequence of Fibonacci numbers.
The first step is to implement the iteration in do+ terms:
POFTHEDAY> (do+
(with (prev 0))
(for x (being 1 :then (prog1 (+ prev x)
(setf prev x))))
(format t "prev: ~A x: ~A~%" prev x)
(stop-when (> x 100)))
prev: 0 x: 1
prev: 1 x: 1
prev: 1 x: 2
prev: 2 x: 3
prev: 3 x: 5
prev: 5 x: 8
prev: 8 x: 13
prev: 13 x: 21
prev: 21 x: 34
prev: 34 x: 55
prev: 55 x: 89
Next, we need to wrap it into the defclause.
This clause can be used in any do+ loops and will be lazily evaluated:
POFTHEDAY> (defclause in-fib ()
`((with (prev 0))
(for ,*iteration-variable*
(being 1 :then (prog1 (+ prev ,*iteration-variable*)
(setf prev ,*iteration-variable*))))))
;; Now we can use it as a clause inside another do+ form:
POFTHEDAY> (do+
(for x (in-fib))
(format t "x: ~A~%" x)
(stop-when (> x 100)))
x: 1
x: 1
x: 2
x: 3
x: 5
x: 8
x: 13
x: 21
x: 34
x: 55
x: 89
NIL
The project repository can be found on GitHub: https://github.com/alessiostalla/doplus
See also :iterate, :for and :series.