
* Rename `make-repeated-sequence-generator' -> `sequence->repeated-generator' * Several tests for `sequence->generator' svn: r17586
94 lines
2.7 KiB
Scheme
94 lines
2.7 KiB
Scheme
#lang scheme/base
|
|
|
|
(require (for-syntax scheme/base)
|
|
scheme/control
|
|
scheme/stxparam scheme/splicing)
|
|
|
|
(provide yield generator in-generator infinite-generator
|
|
sequence->generator sequence->repeated-generator)
|
|
|
|
;; (define-syntax-parameter yield
|
|
;; (lambda (stx)
|
|
;; (raise-syntax-error
|
|
;; #f "yield is only bound inside a sequence generator")))
|
|
|
|
;; (define (procedure->generator proc)
|
|
;; (define tag (make-continuation-prompt-tag))
|
|
;; (define (cont)
|
|
;; (reset-at tag
|
|
;; (let ([r (proc (lambda (r) (shift-at tag k (set! cont k) r)))])
|
|
;; ;; normal return:
|
|
;; (set! cont (lambda () r))
|
|
;; r)))
|
|
;; (lambda () (cont)))
|
|
|
|
;; not using parameterization
|
|
#;
|
|
(define-syntax-rule (generator body0 body ...)
|
|
(let ([tag (make-continuation-prompt-tag)])
|
|
(define yielder
|
|
(let ([yield (lambda (value) (shift-at tag k (set! cont k) value))])
|
|
yield))
|
|
(splicing-syntax-parameterize ([yield (make-rename-transformer #'yielder)])
|
|
(define (cont)
|
|
(reset-at tag
|
|
(let ([retval (begin body0 body ...)])
|
|
;; normal return:
|
|
(set! cont (lambda () retval))
|
|
retval))))
|
|
(define (generator) (cont))
|
|
generator))
|
|
|
|
(define current-yielder
|
|
(make-parameter
|
|
(lambda (v)
|
|
(error 'yield "must be called in the context of a generator"))))
|
|
|
|
(define (yield value)
|
|
((current-yielder) value))
|
|
|
|
(define yield-tag (make-continuation-prompt-tag))
|
|
|
|
(define-syntax-rule (generator body0 body ...)
|
|
(let ()
|
|
(define (cont)
|
|
(define (yielder value)
|
|
(shift-at yield-tag k (set! cont k) value))
|
|
(reset-at yield-tag
|
|
(parameterize ([current-yielder yielder])
|
|
(let ([retval (begin body0 body ...)])
|
|
;; normal return:
|
|
(set! cont (lambda () retval))
|
|
retval))))
|
|
(define (generator) (cont))
|
|
generator))
|
|
|
|
(define-syntax-rule (infinite-generator body0 body ...)
|
|
(generator (let loop () body0 body ... (loop))))
|
|
|
|
(define stop-value (gensym))
|
|
|
|
(define-sequence-syntax in-generator
|
|
(syntax-rules ()
|
|
[(_ body0 body ...)
|
|
(in-producer (generator body0 body ... stop-value) stop-value)])
|
|
(lambda (stx)
|
|
(syntax-case stx ()
|
|
[((id ...) (_ body0 body ...))
|
|
#'[(id ...)
|
|
(in-producer (generator body0 body ... stop-value) stop-value)]])))
|
|
|
|
(define (sequence->generator sequence)
|
|
(generator (for ([i sequence]) (yield i))))
|
|
|
|
(define (sequence->repeated-generator sequence)
|
|
(sequence->generator (in-cycle sequence)))
|
|
|
|
#|
|
|
;; examples
|
|
(for/list ([i (in-generator (for-each yield '(1 2 3)) (yield 'four))]) i)
|
|
(for*/list ([i (in-generator (for-each yield '(1 2 3)) (yield 'four))]
|
|
[j (in-generator (yield 'X) (yield '-))])
|
|
(list i j))
|
|
|#
|