Next: srfi eager-comp spec qualifiers, Up: srfi eager-comp spec [Index]

- Syntax:
**do-ec**`qualifier*``command` Evaluate the

`command`exactly once for each binding in the sequence defined by the qualifiers. If there are no qualifiers`command`is evaluated exactly once. The expression is evaluated for its side–effects only. The result of the comprehension is unspecified.

- Syntax:
**list-ec**`qualifier*``expression` The list of values obtained by evaluating

`expression`once for each binding in the sequence defined by the qualifiers. If there are no qualifiers the result is the list with the value of`expression`.

- Syntax:
**append-ec**`qualifier*``expression` The list obtained by appending all values of

`expression`, which must all be lists. Think of it as:(apply append (list-ec

`qualifier*``expression`))

- Syntax:
**string-ec**`qualifier*``expression` The string of all values of

`expression`. Think of it as:(list->string (list-ec

`qualifier*``expression`))

- Syntax:
**string-append-ec**`qualifier*``expression` The string obtained by appending all values of

`expression`, which must all be strings. Think of it as:(apply string-append (list-ec

`qualifier*``expression`))

- Syntax:
**vector-ec**`qualifier*``expression` The vector of all values of

`expression`. Think of it as:(list->vector (list-ec

`qualifier*``expression`))

- Syntax:
**vector-of-length-ec**`k``qualifier*``expression` The vector of all values of

`expression`, of which there must be exactly`k`. This comprehension behaves like`vector-ec`

but can be implemented more efficiently.

- Syntax:
**sum-ec**`qualifier*``expression` The sum of all values of

`expression`. Think of it as:(apply + (list-ec

`qualifier*``expression`))

- Syntax:
**product-ec**`qualifier*``expression` The product of all values of

`expression`. Think of it as:(apply * (list-ec

`qualifier*``expression`))

- Syntax:
**min-ec**`qualifier*``expression` - Syntax:
**max-ec**`qualifier*``expression` The minimum and maximum of all values of

`expression`. The sequence of values must be non-empty. Think of these as(apply min (list-ec

`qualifier*``expression`)) (apply max (list-ec`qualifier*``expression`))If you want to return a default value in case the sequence is empty you may want to consider:

(fold3-ec 'infinity

`qualifier*``expression`min min)

- Syntax:
**any?-ec**`qualifier*``test` Tests whether any value of

`test`in the sequence of bindings specified by the qualifiers is non–`#f`

. If this is the case,`#t`

is returned, otherwise`#f`

. If there are no bindings at all, in the sequence specified by the qualifiers, then the result is`#f`

. The enumeration of values stops after the first non–`#f`

encountered.

- Syntax:
**every?-ec**`qualifier*``test` Tests whether all values of

`test`are non–`#f`

. If this is the case,`#t`

is returned, otherwise`#f`

. If the sequence is empty the result is`#t`

. Enumeration stops after the first`#f`

.

- Syntax:
**first-ec**`default``qualifier*``expression` - Syntax:
**last-ec**`default``qualifier*``expression` The first or last value of

`expression`in the sequence of bindings specified by the qualifiers. Before enumeration, the result is initialized with the value of`default`; so this will be the result if the sequence is empty. Enumeration is terminated in`first-ec`

when the first value has been computed.

- Syntax:
**fold-ec**`x0``qualifier*``expression``f2`) - Syntax:
**fold3-ec**`x0``qualifier*``expression``f1``f2`) Reduce the sequence

`x`[0],`x`[1], …,`x`[n-1] of values obtained by evaluating`expression`once for each binding as specified by`qualifier*`. The arguments`x0`,`f2`, and`f1`, all syntactically equivalent to`expression`, specify the reduction process.The reduction process for

`fold-ec`

is defined as follows. A reduction variable`x`is initialized to the value of`x0`, and for each`k`in`{0, ..., n-1}`

the command:(set! x (f2 x[k] x))

is evaluated. Finally,

`x`is returned as the value of the comprehension.The reduction process for

`fold3-ec`

is different. If and only if`n = 0`

, i.e. the sequence is empty, then`x0`is evaluated and returned as the value of the comprehension. Otherwise, a reduction variable`x`is initialized to the value of`(f1 x[0])`

, and for each`k`in`{1, ..., n-1}`

the command:(set! x (f2 x[k] x))

is evaluated. Finally,

`x`is returned as the value of the comprehension.As the order of the arguments suggests,

`x0`is evaluated outside the scope of the qualifiers, whereas the reduction expressions involving`f1`and`f2`are inside the scope of the qualifiers (so they may depend on any variable introduced by the qualifiers). Note that`f2`is evaluated repeatedly, with any side–effect or overhead this might have.The main purpose of these comprehensions is implementing other comprehensions as special cases. They are generalizations of the procedures

`fold`

and`reduce`

in the sense of SRFI-1. (Concerning naming and argument order, please refer to the discussion archive of SRFI-1, in particular the posting [Folds].) Note that`fold3-ec`

is defined such that`x0`is only evaluated in case the sequence is empty. This allows raising an error for the empty sequence, as in the example definition of`min-ec`

below.

An important aspect of this SRFI is a modular mechanism to define
application–specific 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 () [(list-ec etc1 etc ...) (reverse (fold-ec '() etc1 etc ... cons))])) (define-syntax min-ec (syntax-rules () [(min-ec etc1 etc ...) (fold3-ec (min) etc1 etc ... min min)]))

Note that the pattern

matches the syntax
`etc1` ...`qualifier*` `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.

Next: srfi eager-comp spec qualifiers, Up: srfi eager-comp spec [Index]