[plt-scheme] comprehensions and iterations (in v4.0, maybe)

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Jun 11 23:06:54 EDT 2007

For version 4.0, I'd like to establish an "official" syntax for list
comprehensions and iterations.

The problem is that there doesn't seem to be a specific form that
everyone likes --- though there's broad agreement that having some form
would be better than none.

After gathering a few opinions, my goal is to find a form that offends
relatively few people. (It may not work.)


SRFI-42's `list-ec' and `do-ec' are the most successful efforts for
Scheme iterations and comprehensions, and I think that the underlying
model is basically right. SRFI-42 covers the kinds of things that list
comprehensions express in many other languages (Haskell, Python, etc.).
Still, SRFI-42 is foreign enough that I can't bring myself to use it,
and some others that I've talked to feel similarly.


The "for.ss" library that's now in the "mzlib" collection of SVN is an
attempt to fit the SRFI-42 model into a syntax that is more consistent
with other Scheme binding forms.

Currently, the "for.ss" forms are documented only in the new guide and
reference manual. For those who don't build from SVN, here's the right
starting point (in a copy that I put on my web site):

 http://www.cs.utah.edu/~mflatt/tmp/newdoc/guide/guide_for.html


Here are some quick examples:

  > (for ([i (in-range 3)])
      (display i))
  012

  > (for/list ([i (in-range 3)])
      (* i i))
  (0 1 4)

  > (for/list ([i (in-naturals 1)]
               [chapter '("Intro" "Details" "Conclusion")])
      (format "~a. ~a" i chapter))
  ("1. Intro" "2. Details" "3. Conclusion")

  > (for/list ([i (in-naturals 1)]
               [chapter '("Intro" "Details" "Conclusion")]
               #:when (odd? i))
      (format "~a. ~a" i chapter))
  ("1. Intro" "3. Conclusion")

As you can see, the syntax of `for' is mostly `let'-like.

Unlike `...-ec', iteration for multiple bindings is in parallel; if you
want nested iteration, use `for*...':

  > (for*/list ([book '("Guide" "Ref.")]
                [chapter '("Intro" "Details")])
      (string-append book " " chapter))
  ("Guide Intro" "Guide Details" "Ref. Intro" "Ref. Details")

Another departure from the SRFI-42 model is that the right-hand side of
a `for' or `for/list' clause is an expression that produces a
first-class sequence value; it doesn't have to have a particular shape.
If you use sequence constructors like `in-range' and `in-list' directly
in a `for' clause, however, then faster code is generated --- just like
using a type-specific clause in SRFI-42.


Whether `for' is a syntactic improvement over SRFI-42 is certainly
subject to debate, as is whether the improvement (to some eyes) is
enough to be worth syntactic incompatibility with SRFI-42. I think it's
an improvement, and I think that comprehensions are useful enough to
have them integrated as nicely as possible with the rest of the
language.

Anyway, the topic is now "officially" open for discussion...

But please note: whatever we do, we almost certainly won't try to
promote a new looping construct that does everything. I'm convinced
that an iteration construct should be limited to the kinds of things
that SRFI-42 handles (as noted above). In other words, as much as I
like Olin's loop-macro paper, don't try to tell me about it in this
thread. :)

Matthew



Posted on the users mailing list.