Previous: loops comprehensions fold, Up: loops comprehensions [Index]
To create a new comprehension a hygienic macro with that name is
defined. The macro transforms the new comprehension patterns into
instances of do-ec
, which is the most fundamental eager
comprehension, or any other comprehension already defined.
For example, the following code defines list-ec
and min-ec
in terms of fold-ec
and fold3-ec
:
(define-syntax list-ec (syntax-rules () ((_ ?etc1 ?etc ...) (reverse (fold-ec '() ?etc1 ?etc ... cons))))) (define-syntax min-ec (syntax-rules () ((_ ?etc1 ?etc ...) (fold3-ec (min) ?etc1 ?etc ... min min))))
Note that the pattern ‘?etc1 ...’ matches qualifier* and expression without separate access to qualifier* and expression. In order to define a comprehension that does need explicit access to the expression part, the following method is used.
First, all qualifiers are collected into a nested–qualifier, and then
the “exactly one qualifier” case is implemented. For illustration,
the following code defines fold3-ec
in terms of do-ec
:
(define-syntax fold3-ec (syntax-rules (nested) ((fold3-ec x0 (nested q1 ...) q etc1 etc2 etc3 etc ...) (fold3-ec x0 (nested q1 ... q) etc1 etc2 etc3 etc ...)) ((fold3-ec x0 q1 q2 etc1 etc2 etc3 etc ...) (fold3-ec x0 (nested q1 q2) etc1 etc2 etc3 etc ...)) ((fold3-ec x0 expression f1 f2) (fold3-ec x0 (nested) expression f1 f2)) ((fold3-ec x0 qualifier expression f1 f2) (let ((result #f) (empty #t)) (do-ec qualifier (let ((value expression)) ; don't duplicate code (if empty (begin (set! result (f1 value)) (set! empty #f)) (set! result (f2 value result))))) (if empty x0 result)))))
Finally, observe that the newly defined fold3-ec
comprehension
inherits all types of qualifiers supported by do-ec
, including
all application–specific generators; no further definitions are
necessary.