Common Lisp How to Continue Iteration Without Looping
2.9 Advanced iteration
2.9.1 Advanced iteration methods
The following syntax is used for iterating over sequences, arrays, hash tables, and similar structures: {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:
-
element
,elements
- Use these loop methods to iterate over elements of Common Lisp sequences and of all structures that are accessed by the Common Lisp function
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 - If a Common Lisp special form
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
-
array-element
,array-elements
- These loop methods are provided for backward compatibility to iterate over elements in arrays. They are equivalent to using the form
(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
-
hash-key
,hash-keys
- These loop methods access each key entry of a hash table. If you specify the name
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")
-
hash-value
,hash-values
- These loop methods access each value entry of a hash table. If you specify the name
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")
-
present-symbol
,present-symbols
- Use these loop methods to iterate over package symbols whose string-to-symbol mappings are defined in, and are thus local to, the package. The package to be iterated over is specified in the same way that package arguments to the Common Lisp function
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
-
symbol
,symbols
- Use these loop methods to iterate over package symbols that are accessible from a given package. You specify the package to be iterated over in the same way that you specify package arguments to the Common Lisp function
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...)
-
external-symbol
,external-symbols
- Use these loop methods to iterate over the external symbols of a package. You specify the package to be iterated over in the same way that you specify package arguments to the Common Lisp function
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
- user-defined loop method
- You can define your own loop method by using the macros
defloop
ordefine-loop-method
. See Section 2.10 on page 49 for more information about these macros.
The Loop Facility - 9 SEP 1996
Generated with Harlequin WebMaker
montefioreslosicessir1967.blogspot.com
Source: http://www.lispworks.com/documentation/lcl50/loop/loop-50.html
0 Response to "Common Lisp How to Continue Iteration Without Looping"
Post a Comment