suggested revision
svn: r15812
This commit is contained in:
parent
ec9fc2571a
commit
572f7f849b
|
@ -2,63 +2,53 @@
|
||||||
|
|
||||||
(require (for-syntax scheme/base)
|
(require (for-syntax scheme/base)
|
||||||
scheme/control
|
scheme/control
|
||||||
scheme/stxparam)
|
scheme/stxparam scheme/splicing)
|
||||||
|
|
||||||
(provide yield lambda-generator
|
(provide yield generator in-generator)
|
||||||
define-generator in-generator)
|
|
||||||
|
|
||||||
(define-syntax-parameter yield
|
(define-syntax-parameter yield
|
||||||
(lambda (stx)
|
(lambda (stx)
|
||||||
(raise-syntax-error #f "yield is only bound inside a sequence generator")))
|
(raise-syntax-error #f "yield is only bound inside a sequence generator")))
|
||||||
|
|
||||||
;; better version of shift/reset using continuation tags also use a
|
;; (define (procedure->generator proc)
|
||||||
;; unique value to determine the end of the sequence instead of using #f
|
;; (define tag (make-continuation-prompt-tag))
|
||||||
(define-syntax lambda-generator
|
;; (define (cont)
|
||||||
(syntax-rules ()
|
;; (reset-at tag
|
||||||
[(_ (args ...) body0 bodies ...)
|
;; (let ([r (proc (lambda (r) (shift-at tag k (set! cont k) r)))])
|
||||||
(lambda (args ...)
|
;; ;; normal return:
|
||||||
(let* ([last (gensym)]
|
;; (set! cont (lambda () r))
|
||||||
;; current is a function that invokes user code and
|
;; r)))
|
||||||
;; produces values
|
;; (lambda () (cont)))
|
||||||
[current
|
|
||||||
(lambda ()
|
|
||||||
;; a unique tag to jump to
|
|
||||||
(define tag (make-continuation-prompt-tag))
|
|
||||||
;; give the value to the sequence
|
|
||||||
(define (next value) (shift-at tag f (values value f)))
|
|
||||||
(syntax-parameterize ([yield (make-rename-transformer #'next)])
|
|
||||||
(reset-at tag body0 bodies ... (values #f last))))]
|
|
||||||
[seq
|
|
||||||
(make-do-sequence
|
|
||||||
(lambda ()
|
|
||||||
(values
|
|
||||||
;; produce a value and a continuation
|
|
||||||
(lambda (i)
|
|
||||||
(let-values ([(value next) (current)])
|
|
||||||
;; set! is ugly but can we do better?
|
|
||||||
(set! current next)
|
|
||||||
value))
|
|
||||||
void
|
|
||||||
(void)
|
|
||||||
(lambda (x) (not (eq? last current)))
|
|
||||||
(lambda (v) (not (eq? last current)))
|
|
||||||
(lambda (x v) (not (eq? last current))))))])
|
|
||||||
seq))]))
|
|
||||||
|
|
||||||
;; use define-sequence-syntax to be more in sync with other for loop constructs
|
(define-syntax-rule (generator body0 body ...)
|
||||||
(define-syntax in-generator
|
(let ([tag (make-continuation-prompt-tag)])
|
||||||
(syntax-rules ()
|
(define y
|
||||||
[(_ body0 bodies ...)
|
(let ([yield (lambda (r) (shift-at tag k (set! cont k) r))]) yield))
|
||||||
((lambda-generator () body0 bodies ...))]))
|
(splicing-syntax-parameterize ([yield (make-rename-transformer #'y)])
|
||||||
|
(define (cont)
|
||||||
|
(reset-at tag
|
||||||
|
(let ([r (begin body0 body ...)])
|
||||||
|
;; normal return:
|
||||||
|
(set! cont (lambda () r))
|
||||||
|
r))))
|
||||||
|
(lambda () (cont))))
|
||||||
|
|
||||||
(define-syntax define-generator
|
(define stop-value (gensym))
|
||||||
|
|
||||||
|
(define-sequence-syntax in-generator
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
[(_ (name args ...) body0 bodies ...)
|
[(_ body0 body ...)
|
||||||
(define name (lambda-generator (args ...) body0 bodies ...))]))
|
(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)]])))
|
||||||
|
|
||||||
#|
|
#|
|
||||||
;; example
|
;; examples
|
||||||
(define-generator (blah)
|
(for/list ([i (in-generator (for-each yield '(1 2 3)) (yield 'four))]) i)
|
||||||
(for ([x (in-range 0 10)])
|
(for*/list ([i (in-generator (for-each yield '(1 2 3)) (yield 'four))]
|
||||||
(yield x)))
|
[j (in-generator (yield 'X) (yield '-))])
|
||||||
|
(list i j))
|
||||||
|#
|
|#
|
||||||
|
|
Loading…
Reference in New Issue
Block a user