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