[plt-dev] I love Haskell (not an April Fools Joke!), feature request for 'for'

From: Eli Barzilay (eli at barzilay.org)
Date: Thu Apr 2 20:48:23 EDT 2009

On Apr  2, Sam TH wrote:
> 
> Here's the implementation of `cycle' (which should probably be in the
> sequence library):
> [...]

Below is a better implementation of `in-sequences' using a
`append-sequences' helper.  It's also implementing `in-cycle', which
just uses the same `append-sequences' utility with a cyclic list of
the inputs.  (And BTW, it doesn't cache the items, which looks like a
mistake to do.)

After that I implemented an `in-lazy' macro, using `in-thunk' (with
apologies for Ryan...) -- the cute thing is that you can then
implement a cyclic iteration with:

  (for ([i (letrec ([seq (in-sequences (in-range 4) (in-lazy seq))])
             seq)])
    (printf "i = ~s\n" i))

or even:

  (for ([i (letrec ([seq (in-lazy (in-sequences (in-range 4) seq))])
             seq)])
    (printf "i = ~s\n" i))

But there's a problem with this -- AFAICT, there is no way for a
sequence to just return a new sequence to iterate over, which would be
a tail-call kind of transfer to the new sequence.  So the `in-lazy'
thing must create a sequence that forever wraps the input sequence.
The result is a growing chain of sequence proxies.  Maybe there's a
nice way to extend the api so a sequence can stop and return a
"continuation sequence", but looking at the code that change doesn't
look easy.

In any case, I don't think that there are any practical uses of an
`in-lazy', so it looks to my like `in-sequences' and `in-cycle' are
enough as an addtion.



#lang scheme

(define (append-sequences seqs)
  (define (seqs->m+g+r seqs)
    (and (pair? seqs)
         (let-values ([(more? get) (sequence-generate (car seqs))])
           (list* more? get (cdr seqs)))))
  (make-do-sequence
   (lambda ()
     ;; place is (cur-more? cur-get rest-seqs ...) or #f
     (values (lambda (m+g+r) ((cadr m+g+r)))
             (lambda (m+g+r)
               (let loop ([m+g+r m+g+r])
                 (if (and (pair? m+g+r) (not ((car m+g+r))))
                   (seqs->m+g+r (cddr m+g+r))
                   m+g+r)))
             (seqs->m+g+r seqs)
             (lambda (p) p)
             (lambda _ #t)
             (lambda _ #t)))))

(define (in-sequences . seqs) (append-sequences seqs))
(define (in-cycle . seqs) (append-sequences (shared ([x (append seqs x)]) x)))

(define (in-thunk sthunk)
  (make-do-sequence
   (lambda ()
     (define-values [more? get] (sequence-generate (sthunk)))
     (values (lambda (_) (get))
             void
             (void)
             (lambda (_) (more?))
             (lambda _ #t)
             (lambda _ #t)))))
(define-syntax-rule (in-lazy seq-expr) (in-thunk (lambda () seq-expr)))

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


Posted on the dev mailing list.