chickadee » foof-loop » IN-STRING

(IN-VECTOR <vector> [<low> [<high>]])syntax
(IN-STRING <string> [<low> [<high>]])syntax
(IN-VECTOR-REVERSE <vector> [<high> [<low>]])syntax
(IN-STRING-REVERSE <string> [<high> [<low>]])syntax

Usage:

   (FOR <element> [<index>] (IN-VECTOR         <vector> [<low> [<high>]]))
   (FOR <element> [<index>] (IN-STRING         <string> [<low> [<high>]]))
   (FOR <element> [<index>] (IN-VECTOR-REVERSE <vector> [<high> [<low>]]))
   (FOR <element> [<index>] (IN-STRING-REVERSE <string> [<high> [<low>]]))

These iterate for each successive index in the vector or string, respectively, binding the variable <index>, if supplied, to that index, and the variable <element> to the element at that index.

IN-VECTOR and IN-STRING run from <low>, inclusive, to <high>, exclusive; IN-VECTOR-REVERSE and IN-STRING-REVERSE run from <high>, exclusive, to <low>, inclusive.

<Vector> or <string> must be a vector or a string, respectively. <Low> and <high>, if supplied, must be exact, non-negative integers, and valid bounds for <string> or <vector>. The default values of <low> and <high> are 0 and the length of the vector or string, respectively. <Vector>, <string>, <low>, and <high> are all evaluated once before the loop begins.

<Index> is a loop variable; its value in the final expression is the value of the last bound of iteration (the value of <high> for IN-VECTOR and IN-STRING; the value of <low> for IN-VECTOR-REVERSE and IN-STRING-REVERSE). With the reverse iterators, IN-VECTOR-REVERSE and IN-STRING-REVERSE, explicitly updating <index> when continuing the loop will cause the next value seen by the loop body to be one *less* than what the index was updated to. That is, on loop entry, <index> is assumed to be an exclusive upper bound, and so it is tested for termination and then decremented to find the actual index.

<Element> is a body variable.

Because the lower bound is inclusive and the upper bound is exclusive, for IN-VECTOR and IN-STRING, the first value of <index> is <low>, and the value of <index> in the final expression is <high>; while for IN-VECTOR-REVERSE and IN-STRING-REVERSE, the first value of <index> in the loop body is one less than <high>, and the value of <index> in the final expression is <low>.

   (loop ((for a i (in-vector '#(foo bar baz)))
          (for b j (in-string-reverse "abcdefghi" 6 3)))
     => (list i j)
     (write (list a i b j))
     (newline))
   ;Value: (3 3)
   
   ;; Output:
   ;(foo 0 f 5)
   ;(bar 1 e 4)
   ;(baz 2 d 3)
   
   ;;; Find the first index of an element satisfying a predicate.
   
   (define (vector-index vector predicate)
     (loop proceed ((for elt index (in-vector vector)))
       (if (predicate elt)
           index
           (proceed))))
   
   ;;; Copy characters from one string to another.
   
   (define (string-copy! target tstart source sstart send)
     (loop ((for char (in-string source sstart send))
            (with index tstart (+ index 1)))
       (string-set! target index char)))
   
   (loop proceed 
       ((for v i
          (in-vector
           '#(a b c d e f g h i j k l m n o p q r s t u v w x y z))))
     (write (list v i))
     (newline)
     (proceed (=> i (+ 1 (* i 2)))))
   ;; Output:
   ;(a 0)
   ;(b 1)
   ;(d 3)
   ;(h 7)
   ;(p 15)