2.9 Advanced iteration
{for
|as
} var [type-spec]being
{each
|the
} loop-method-name
[in
|of
]
[preposition expression]*
The var argument takes on the value of each element in the data structure expression by using the loop method specified by the loop-method-name argument. The data type of var can be specified by the type-spec argument.
For the purposes of readability, the loop keywordeach
should follow the loop keywordbeing
when the reference to the elements in the data structure is singular. The loop keywordthe
is used afterbeing
when a plural reference to the elements of the data structure is made in the loop method. These keywords are syntactically equivalent; you can useeach
with plural references andthe
with singular references without causing an error.
Iteration stops when there are no more elements in the specified expression that can be referenced in the way defined by the specified loop method.
For each loop method, there is a set of allowable prepositions; the most common prepositions areof
andin
. All of the prepositions listed under "Syntax 1" of {for
|as
} in Section 2.2 on page 12 are also allowed. Also, for the purposes of parsing these advanced iteration constructs, the loop keywordusing
is treated as a preposition.
The loop-method-name argument can be one of the following methods; the singular and plural forms are interchangeable:
elt
. Common Lisp sequences include lists, vectors, and strings. You can use the macrodefloop
to define an additional form of sequential iteration; see Section 2.10 on page 49
the
is wrapped around the expression to be iterated over, the Compiler recognizes it as a declaration. In particular, by usingthe
withelements
, you can declare array types within the Loop Facility. Arrays declared to be simple, with known rank and element types, are especially optimized by Liquid Common Lisp.
;; Print the elements of a list. > (loop for x being the elements of '(1 2 3) do (print x)) 1 2 3 NIL;; Print the elements of a vector up to a particular index. > (loop for x being the elements of #(a b c d e) to 3 do (print x)) A B C D NIL
;; Print the characters in a string, which is also a vector. > (loop for x being the elements of "abcde" from 2 do (print x)) #\c #\d #\e NIL
;; Print the elements of a bit vector. > (loop for x being the elements of #*101 do (print x)) 1 0 1 NIL ; Since the loop type-spec syntax is not rich enough to specify ; all of the refinements possible over sequences, you can use the ; Common Lisp THE construct around the sequence expression.
> (setq z "abc") "abc"
> (loop for x being the elements of (the simple-string z) do (print x)) #\a #\b #\c NIL
(the array array-name)
as the sequence argument for anelements
method.
;; Seed an array with values, and return all of the values ;; in the array. > (let ((array (make-array 10))) (loop for i from 0 to 9 do (setf (aref array i) i)) (loop for a being the array-elements of array collect a)) (0 1 2 3 4 5 6 7 8 9);; Print the elements of a bit vector, which is a one-dimensional ;; array. > (loop for x being the array-elements of #*101 do (print x)) 1 0 1 NIL
;; Print the elements of a string, which is a one-dimensional ;; array. > (loop for x being the array-elements of "fun" do (print x)) #\f #\u #\n NIL
value
in ausing
construct with one of these loop methods, the iteration can optionally access the keyed value. The order in which the keys are accessed is undefined; empty slots in the hash table are ignored.
;; Create a hash table, and put some values in it. Count the ;; number of odd keys in the table, and then collect both the keys ;; and values into an alternating list. > (setq *ht* (make-hash-table)) #<Hash-Table 59C5AB> > (loop for i from 1 to 10 do (setf (gethash i *ht*) (format nil "~D" i))) NIL> (loop for k being the hash-keys of *ht* when (oddp k) count k) 5
> (loop for integer being the hash-keys of *ht* using (value string) nconc (list integer string)) (1 "1" 2 "2" 3 "3" 4 "4" 5 "5" 6 "6" 7 "7" 8 "8" 9 "9" 10 "10")
key
in ausing
construct with one of these loop methods, the iteration can optionally access the key that corresponds to the value. The order in which the keys are accessed is undefined; empty slots in the hash table are ignored.
;;; Create a hash table, and put some values in it. Count the ;;; number of values of length greater than 1, and then collect ;;; both the keys and values into an alternating list. > (setq *ht* (make-hash-table)) #<Hash-Table 59C5AB>> (loop for i from 1 to 10 do (setf (gethash i *ht*) (format nil "~D" i))) NIL
> (loop for str being the hash-values of *ht* count (> (length str) 1)) 1
> (loop for string being the hash-values of *ht* using (key integer) nconc (list integer string)) (1 "1" 2 "2" 3 "3" 4 "4" 5 "5" 6 "6" 7 "7" 8 "8" 9 "9" 10 "10")
find-package
are specified. If you do not specify the package for the iteration, the current package is used. If you specify a package that does not exist, an error is signaled.
;; Count the symbols in a new package, which should be empty. > (let ((pkg (make-package (gensym)))) (loop for s being each present-symbol in pkg count s)) 0
find-package
. If you do not specify the package for the iteration, the current package is used. If you specify a package that does not exist, an error is signaled.
;; Gather symbols in a new package, which inherits from the ;; LISP package. > (let ((pkg (make-package (gensym)))) (loop for s being each symbol in pkg collect s)) (POSITION PUSHNEW READ-FROM-STRING...)
find-package
. If you do not specify the package for the iteration, the current package is used. If you specify a package that does not exist, an error is signaled.
;; Gather external symbols in a new package with a few entries. > (let ((pkg (make-package "TEMP"))) (intern "A" pkg) (export (intern "B" pkg) pkg) (intern "C" pkg) (loop for s being the external-symbols in pkg collect s)) TEMP:B
defloop
ordefine-loop-method
. See Section 2.10 on page 49 for more information about these macros.
Generated with Harlequin WebMaker