Next: , Previous: COLLECTING/WITH-COLLECTORS Examples, Up: LOOP --> Loopless


2.3 for* Examples

First, here's a trivial example of using “for-as-arithmetic” outside of loop with for*. There is a frequent need to have arithmetic stepping of a variable. Thanks to for*, you can combine loop's intuitive syntax for this with any looping construct whatsoever. You simply have to wrap the body of the loop with for* and then call step* at the start of each iteration.

     (mapcar (for* ((i downfrom 10 by 3))
               (lambda (element)
                 (step*)
                 (list element i (* i 10))))
             '(a b c))
     ==
     (loop for element in '(a b c)
           for i downfrom 10 by 3
           collect (list element i (* i 10)))
     ⇒ ((A 10 100) (B 7 70) (C 4 40))

This next example is illustrative of the following aspects of typical for* usage:

Note that we couldn't have put the step* call as the first statement in the let, because then we would have accessed i, a for* binding, before step* has been called at least once, with undefined consequences.

     (mapcar (for* ((i from 1)
                    (firstp = t then nil))
               (lambda (symbol)
                 (step*)
                 (let ((square (* i i)))
                   (list i
                         symbol
                         (if firstp
                             'first
                             square)
                         (- square)))))
             '(a b c))

Here's a big unrealistic example of for* usage that illustrates most of its features. In most situations, you'll use (and need) one or two for* bindings at a time only.

     (mapcar (for* ((i downfrom (expt 2 5) by 3)
                    (oddp = (oddp i))
                    (j from 0)
                    (firstp = t then nil)
                    (k downfrom 0 by 2))
               (lambda (element)
                 (step*)
                 `((element ,element) (i ,i) (oddp ,oddp)
                   (j ,j) (firstp ,firstp) (k ,k)
                   ((+ i j k) ,(+ i j k)))))
             '(a b c))
     ==
     (loop for element in '(a b c)
           for i downfrom (expt 2 5) by 3
           for oddp = (oddp i)
           for j from 0
           for firstp = t then nil
           for k downfrom 0 by 2
           collect `((element ,element)
                     (i ,i) (oddp ,oddp)
                     (j ,j) (firstp ,firstp) (k ,k)
                     ((+ i j k) ,(+ i j k))))
     ⇒
     (((ELEMENT A) (I 32) (ODDP NIL) (J 0) (FIRSTP T) (K 0) ((+ I J K) 32))
      ((ELEMENT B) (I 29) (ODDP T) (J 1) (FIRSTP NIL) (K -2) ((+ I J K) 28))
      ((ELEMENT C) (I 26) (ODDP NIL) (J 2) (FIRSTP NIL) (K -4) ((+ I J K) 24)))