Previous: loops comprehensions fold, Up: loops comprehensions


47.2.8 Defining new comprehensions

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.