Previous: , Up: loops comprehensions   [Index]


1.16.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.