[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.14 srfi-42 - Eager comprehensions

Module: srfi-42

This module provides a generic comprehension mechanism, which some other languages (e.g. Haskell and Python) provides as a built-in mechanism. It provides rich set of operators so it can be used as not only a list generator but a generic loop construct (actually, some may say it is as powerful/evil as Common Lisp's loop macro).

It is also runs eagerly, that is, if it generates a list, it creates the entire list when evaluated, instead of generate the elements on demand. Thus it can't represent an infinite sequence, which Haskell's comprehension naturally can. In Scheme, you can use streams built on top of delayed evaluation for such purpose.

Eager comprehension examples

Let's begin with some examples.

Generate a list of squares for the first five integers:

 
(list-ec (: i 5) (* i i)) ⇒ (0 1 4 9 16)

Generate set of pair of numbers (x y), where x is between 2 (inclusive) and 5 (exclusive), and y is between 1 (inclusive) and x (exclusive).

 
(list-ec (: x 2 5) (: y 1 x) (list x y))
  ⇒ ((2 1) (3 1) (3 2) (4 1) (4 2) (4 3))

The above two examples can be written in Haskell as the followings:

 
[ i*i   | i <- [0..4] ]
[ (x,y) | x <- [2..4], y <- [1..x-1] ]

Note the differences: (1) In Haskell, the body expression to yield the elements comes first, followed by qualifiers (selectors). In srfi-42, the body expression comes last. (2) In srfi-42, range operator's lower bound is inclusive but its upper bound is exclusive.

List a set of numbers (a b c d), where a^3+b^3 = c^3+d^3:

 
(define (taxi-number n)
  (list-ec (: a 1 n)
           (: b (+ a 1) n)
           (: c (+ a 1) b)
           (: d (+ c 1) b)
           (if (= (+ (expt a 3) (expt b 3))
                  (+ (expt c 3) (expt d 3))))
           (list a b c d)))

You can generate not only a list, but other sequences:

 
(vector-ec (: i 5) i) ⇒ #(0 1 2 3 4)
(string-ec (: i 5) (integer->char (+ i 65))) ⇒ "ABCDE"

Or apply folding operations:

 
(sum-ec (: i 1 100) i)
  ⇒ 4950    ;; sum of integers from 1 below 100.
(product-ec (: i 1 10) i)
  ⇒ 362880 ;; ... and product of them.

Comprehension macros

Each comprehension takes the following form.

 
(comprehension-macro qualifierbody)

Evaluates body repeatedly as specified by qualifiers. Depending on the type of comprehension, the results of body may be either collected to create an aggregate (list, vector, string, ...), folded by some operator (sum, product, min, max, ...), or simply discarded.

A few comprehensions takes extra values before qualifiers or after bodies.

Macro: do-ec qualifier … body

[SRFI-42]

Macro: list-ec qualifier … body

[SRFI-42]

Macro: append-ec qualifier … body

[SRFI-42]

Macro: string-ec qualifier … body
Macro: string-append-ec qualifier … body

[SRFI-42]

Macro: vector-ec qualifier … body

[SRFI-42]

Macro: vector-of-length-ec qualifier … body

[SRFI-42]

Macro: sum-ec qualifier … body
Macro: product-ec qualifier … body
Macro: min-ec qualifier … body
Macro: max-ec qualifier … body

[SRFI-42]

Macro: any?-ec qualifier … test
Macro: every?-ec qualifier … test

[SRFI-42]

Macro: first-ec default qualifier … body
Macro: last-ec default qualifier … body

[SRFI-42]

Macro: fold-ec x0 qualifier … expr f2
Macro: fold3-ec x0 qualifier … expr f1 f2

[SRFI-42]

Qualifiers

Control qualifiers

EC Qualifier: if test
EC Qualifier: not test
EC Qualifier: and test
EC Qualifier: or test
EC Qualifier: begin test
EC Qualifier: nested test

Generational qualifiers

EC Qualifier: : vars arg1 args …
EC Qualifier: :list vars arg1 args …
EC Qualifier: :vector vars arg1 args …
EC Qualifier: :string vars arg1 args …
EC Qualifier: :integers vars
EC Qualifier: :range vars stop
EC Qualifier: :range vars start stop
EC Qualifier: :range vars start stop step
EC Qualifier: :real-range vars stop
EC Qualifier: :real-range vars start stop
EC Qualifier: :real-range vars start stop step
EC Qualifier: :char-range vars min max
EC Qualifier: :port vars port
EC Qualifier: :port vars port read-proc
EC Qualifier: :dispatched vars dispatch arg1 args …
EC Qualifier: :do (lb …) ne1? (ls …)
EC Qualifier: :do (let (ob …) oc …) (lb …) ne1? (let (ib …) ic …) ne2? (ls …)
EC Qualifier: :let vars expr
EC Qualifier: :parallel generator …
EC Qualifier: :while generator expr
EC Qualifier: :until generator expr

[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated by Shiro Kawai on October, 7 2008 using texi2html 1.78.