#lang scheme/base
(require scheme/promise scheme/control)
(provide (all-defined-out))
(define (generator->lazy-list g done?)
(let next ()
(delay
(let ((item (g)))
(if (done? item) '()
(cons item (next)))))))
(define gen->ll generator->lazy-list)
(define (values* x) (apply values x))
(define (pass . args) (values* args))
(define (in-lazy-list ll [output pass])
(make-do-sequence
(lambda ()
(define (ll-car x) (output (car (force x))))
(define (ll-cdr x) (cdr (force x)))
(define (ll-more? x) (pair? (force x)))
(values ll-car ll-cdr ll ll-more? void void))))
(define in-ll in-lazy-list)
(define (sequence->list seq) (for/list ((el seq)) el))
(define seq->l sequence->list)
(define (generator->list gen done?) (seq->l (in-gen gen done?)))
(define gen->l generator->list)
(define (in-gen gen done?) (in-ll (gen->ll gen done?)))
(define (find mapper el/false collection)
(prompt
(mapper
(lambda args
(let ((el (apply el/false args)))
(if el (abort el) #f)))
collection)
#f))
(define-syntax-rule (ll-begin . body)
(reset (begin . body) (delay '())))
(define-syntax-rule (ll-produce x)
(shift k (delay (cons x (k #f)))))
(define (ll-end) (abort (delay '())))
(define (ll-acor task-body [pack values*])
(define (produce . xs) (ll-produce (pack xs)))
(ll-begin
(if (eq? 1 (procedure-arity task-body))
(task-body produce)
(task-body produce ll-end))))
(define (in-acor task-body [unpack values*])
(in-ll (ll-acor task-body pass) unpack))
(define (sequence->lazy-list seq [pack values])
(let-values (((more? next) (sequence-generate seq)))
(ll-begin
(let loop ()
(when (more?)
(ll-produce (call-with-values next pack))
(loop))))))
(define seq->ll sequence->lazy-list)
(define (seq->list-ll seq) (seq->ll seq list))
(define (map->ll map collection)
(ll-begin
(map (lambda (el) (ll-produce el)) collection)))
(define (in-map map collection)
(in-ll (map->ll map collection)))
(define (lazy-list->list ll) (seq->l (in-ll ll)))
(define ll->l lazy-list->list)
(define-syntax-rule (for/lazy-list clauses . body)
(ll-begin (for clauses (ll-produce (begin . body)))))
(define-syntax-rule (for/ll . a) (for/lazy-list . a))
(define (ll-map fn ll) (for/ll ((e (in-ll ll))) (fn e)))
(define (ll-uncons x [make-fake-tail (lambda () (error 'll-uncons-null))])
(let ((p (force x)))
(if (null? p)
(ll-uncons (make-fake-tail))
(values (car p) (cdr p)))))
(define-syntax ll-let
(syntax-rules ()
((_ (rest) expr . body)
(let ((rest expr)) . body))
((_ (e es ...) expr . body)
(let-values (((e tail) (ll-uncons expr)))
(ll-let (es ...) tail . body)))))
(define (ll-take in-n in-ll [make-fake-tail (lambda () (error 'll-take-underflow))])
(let next ((n in-n)
(ll in-ll)
(acc '()))
(if (<= n 0)
(values (reverse acc) ll)
(let-values (((e ll+) (ll-uncons ll make-fake-tail)))
(next (sub1 n) ll+ (cons e acc))))))
(define (in-append . seqs)
(in-ll
(apply ll-append
(map seq->list-ll seqs)) values*))
(define (ll-append ll . lls)
(delay
(let ((l (force ll)))
(if (pair? l)
(let ((e (car l))
(ll+ (cdr l)))
(cons e (apply ll-append ll+ lls)))
(if (null? lls)
'()
(force (apply ll-append lls)))))))
(define-struct zipper (element yield)) (define (map->zipper collection [map map-list])
(reset
(map (lambda (el)
(shift k (make-zipper el k)))
collection)))
(define (map-list fn lst)
(map (lambda (el) (or (fn el) el)) lst))
(define zipper-open map->zipper)
(define (zipper-read z) (zipper-element z))
(define (zipper-write z x) ((zipper-yield z) x))
(define (zipper-close z)
(let next ((z z))
(if (zipper? z)
(next (zipper-write z #f))
z)))