You are looking at historical revision 1620 of this page. It may differ significantly from its current revision.
;;;Python-like generators in Scheme
;;;
;;;Michele Simionato (michele.simionato@gmail.com) May 2005
;;;Adapted from http://c2.com/cgi/wiki?SchemeCoroutineExample
;;;Assumes you have the "match" module and "define-macro" enabled
;; in many schemes this is already defined
(define-macro (let/cc k . body)
`(call/cc (lambda (,k) ,@body)))
; to spare parenthesis, real schemers will hate this one ;)
(define-macro (let/ name value . args)
`(match-let ((,name ,value)) ,@args))
;; the core implementation
(define (generator routine)
(let/ (current status) (list routine 'suspended)
(match-lambda*
(() (if (eq? status 'dead)
(error 'dead-generator)
(let/ continuation-and-value
(let/cc exit
(let/ yield
(lambda (value)
(let/cc next
(exit (cons next value))))
(current yield) ; exits from here,
;; except after the last yield
(set! status 'dead)
(error 'dead-generator)))
(if (pair? continuation-and-value)
(begin (set! current (car continuation-and-value))
(cdr continuation-and-value))
continuation-and-value))))
(('status?) status)
(('dead?) (eq? status 'dead))
(('alive?) (not (eq? status 'dead)))
(('kill!) (set! status 'dead)))))
;; an example
(define test
(generator (lambda (yield)
(yield "HELLO!")
(yield "WORLD!")
(display "SORRY, I'M OUT"))))
(test 'status?) ; suspended
(test 'dead?) ; #f
(test 'alive?) ; #t
(test) ; "HELLO!"
(test) ; "WORLD!"
(test) ; "SORRY, I'M OUT"
(test 'status?) ; dead
(test 'dead?) ; #t
(test) ; Error: dead-generator
;; another example:
(define (list->iterator list)
(generator (lambda (yield)
(for-each yield list))))
(define (iterator-empty? iterator)
(iterator 'dead?))
(define my-iterator
(list->iterator (list 1 2 3)))
(my-iterator) ; 1
(my-iterator) ; 2
(my-iterator) ; 3
(iterator-empty? my-iterator) ; #f