[plt-dev] I love Haskell (not an April Fools Joke!), feature request for 'for'
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!