[plt-scheme] PLT v 4.0 discussion - sequences

From: Eli Barzilay (eli at barzilay.org)
Date: Thu Jun 5 08:38:35 EDT 2008

On Jun  4, Mark Engelberg wrote:
> It seems like at a minimum, you'd want to use comprehension syntax
> to be able to express map and filter over existing sequences.  For
> example, the sequence of all square numbers could be:
> (for/sequence ([i (in-naturals)]) (* i i))

This sounds to me like a good idea at a first glance, but of further
thought I don't see any practical use for it.  IIUC, your suggestion
is that I can do something like this:

  ;; print n^2 for all even numbers
  (for ([i (for/sequence ([i (in-naturals)]) (* 2 i))])
    (printf ">>> ~s\n" (* i i)))

The two big problems with this is that it's more complex to write (the
nesting is awkward), and that in practical situations I'd almost
always try to avoid the extra cost.  Plus, in at least cases that I
imagined (like the above), refactoring the code is straightforward:

  ;; print n^2 for all even numbers
  (for ([i (in-naturals)])
    (let ([i (* 2 i)])
      (printf ">>> ~s\n" (* i i))))

The only problem with this is that clear code can result in the "right
drift" problem.  For some of these cases, the new `nest' macro can be
convenient, for example, the above can be written like this:

  ;; print n^2 for all even numbers
  (nest ([for ([i (in-naturals)])]
         [let ([i (* 2 i)])])
    (printf ">>> ~s\n" (* i i)))

Finally, don't forget that there's another way to define new kinds of
`for/*' which work for most cases: just use a macro.  `for/fold' is
particularly useful here.  For example:

  > (define-syntax-rule (for/sum (clause ...) expr)
      (for/fold ([s 0]) (clause ...) (+ s expr)))
  > (for/sum ([i (in-range 0 10)]) (* i i))

There are even the derived forms (look for "iteration forms") that are
designed to make it better:

  > (define-syntax (for/sum stx)
      (syntax-case stx ()
        [(for/sum (clause ...) expr)
         #`(for/fold/derived #,stx ([s 0]) (clause ...) (+ s expr))]))
  > (for/sum (meh) (* i i))
  stdin::123: for/sum: bad sequence bindingq clause at: meh in:
  (for/sum (meh) (* i i))

> What other easy ways could there be to express and create sequences?
> Python uses "yield" to concisely express many generators, which are
> essentially the same as PLT Scheme's sequences, but I don't know
> whether yield is a good fit for the Scheme way of doing things.  Any
> other ideas?

There was a discussion recently with an implementation of a yield kind
of sequence.  (But note that continuation have a runtime price.)

          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!

Posted on the users mailing list.