RSS Feed

Lisp Project of the Day

doplus

You can support this project by donating at:

Donate using PatreonDonate using Liberapay

Or see the list of project sponsors.

dopluslanguage

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.


Brought to you by 40Ants under Creative Commons License