Previous: Trivial Operators Examples, Up: LOOP --> Loopless


2.5 Advanced Examples

The mapcar-like functions are great to accumulate results into a single list, but what if we want to accumulate into multiple lists in different formats simultaneously according to some category criteria? We can simply use the side-effects-only versions of the mapping functions (such as mapal, mapal* and mappl) along with with-collectors. If you don't need to provide multiple lists to the mapping functions, then I'd recommend doing the same with the dolist-like macros instead.

     (defun processor-by-two (process-function)
       (lambda (&rest args)
         (mappl process-function args)))
     
     (with-collectors (even-numbered-plist car-list top-car-and-bottom-cdr-alist)
       (mapal (let ((even-and-car-processor
                     (processor-by-two
                      (lambda (key value)
                        (if (evenp value)
                            (neven-numbered-plist (list key value)))
                        (car-list key)))))
                (lambda (&rest args)
                  (apply even-and-car-processor args)
                  (top-car-and-bottom-cdr-alist (cons (car args) (car (last args))))))
              '((a . 1) (b . 2))
              '((x . -1) (y . -2))
              '((foo . 8) (bar . 16))))
     ==
     ;; The loop version is currently unavailable
     ;; because it's too painful to write. (no kidding!)
     ;; In loop's defense, this is a scenario unlikely to happen in the Real World.
     ⇒
     (FOO 8 B 2 Y -2 BAR 16)
     (A X FOO B Y BAR)
     ((A . 8) (B . 16))

That's the only advanced example for now, if you come across really complex loops please send them my way (via the mailing list or my personal email address), I can advise you on how to convert it to Loopless style if you can't figure it out (or maybe you've found a scenario Loopless actually doesn't handle well, I'd love to see that!) and perhaps incorporate them as examples here.