Macro FOREACH
Package:
CL.EXTENSIONS.ENUMERATIONS
Syntax:
foreach (var object &rest keys) &body forms-and-clauses => result
Arguments and Values:
var---a non evaluated symbol
object---an object instance
keys---a list of key-value pairs
forms-and-clauses---a list of forms and LOOP clauses
Description:
The FOREACH macro is a simplified iteration construct over an enumerable object. FOREACH is a thin macro over LOOP and it mixes, in a hybrid -- and maybe not so beautiful -- style the DOTIMES/DOLIST shape with LOOP clauses.
forms-and-clauses are executed in an environment where var is bound to the elements of the result of
(apply #'enum:enumerate object keys)
If keys contains a non-NIL :reverse keyword,
then the enumeration must be bi-directional and PREVIOUS and
HAS-PREVIOUS-P will be used to traverse it. :reverse and its value
will be still passed to the embedded call to ENUMERATE. This is
obviously only useful only for enumerations that can start "in the
middle".
forms-and-clauses can start with some declarations and then continue with either regular forms or LOOP clauses. After the first LOOP clause appears in FORMS-AND-CLAUSES, standard LOOP rules should be followed.
The result returned by FOREACH is whatever is returned by forms-and-clauses according to standard LOOP semantics.
Examples:
Here are some examples of FORACH.
cl-prompt> (setf le (enumerate '(1 2 3))) #<CONS enumeration ...> cl-prompt> (foreach (i le) (print i)) 1 2 3 NILOf course, FOREACH is smarter than that:
cl-prompt> (foreach (i (vector 'a 's 'd))
(declare (type symbol i))
(print i))
A
S
D
NIL
Apart from declarations, FOREACH is just a macro built on top of
LOOP, therefore you can leverage all the LOOP functionality.
cl-prompt> (foreach (i (vector 1 2 3 4))
(declare (type fixnum i))
when (evenp i)
collect i)
(2 4)
While this creates an admittedly strange hybrid between the
standard DO... operators and LOOP, it does serve the purpose. The
right thing would be to have a standardized way of extending LOOP.
Alas, there is no such luxury.
Finally an example of a reverse enumeration:
cl-prompt> (foreach (i (vector 1 2 3 4 5 6 7 8) :reverse t :start 4)
when (evenp i)
collect i)
(4 2)
Affected By:
None.
Exceptional Situations:
None.
See Also:
ENUMERATION class, BOUNDED-ENUMERATION, NUMBER-ENUMERATION, BI-DIRECTIONAL-ENUMERATION, SEQUENCE-ENUMERATION, LIST-ENUMERATION, ARRAY-ENUMERATION, VECTOR-ENUMERATION, STRING-ENUMERATION, HASH-TABLE-ENUMERATION, NEXT, HAS-NEXT-P, CURRENT, PREVIOUS, HAS-PREVIOUS-P.
Notes:
None.