 ;;                  (for [i (range x)]
 ;;                    (yield i)))
 ;;                100)
-;;   -> () ; or even nothing (?)
-;; but this does
+;;   -> ()
+;; but this does:
 ;;   (generate-by (fn runner [x]
 ;;                  (doseq [i (range x)]
 ;;                    (yield i)))
 ;;                100)
 ;;   -> (0 1 2 3 ...)
 
-(set! *warn-on-reflection* true)
+;; Note: Normally generators are "function" returning different values
+;; on different calls (hence they are not functions, actually). Here
+;; generators are thought of as functions returning "function" which
+;; generate the different values. These functions also throw
+;; NoSuchElementExceptions when there is nothing left to
+;; generate. (See also iterators)
 
-(defmacro make-generator
-  ""
+
+;; Generators
+
+(defmacro- make-generator
+  "Creates a generator from the given function definition, which may
+  use the function \"yield\". The result may be called with arguments
+  to give a function returning all yielded values on subsequent
+  calls."
   [function]
   `(fn [& args#]
      (let [#^SynchronousQueue queue# (SynchronousQueue.),

		(java.util.NoSuchElementException. "No more elements to generate."))
	       next#)))))))

(defmacro defg
  ""
  [name args & body] ; enable docstrings?
  `(defn ~name [& args#]
     (let [gen# (make-generator (fn ~name ~args ~@body))]
       (apply gen# args#))))

(defn generate
  ""
  [generator]
  (let [eos (gensym),
	runner (fn runner []

(ns conexp.contrib.generators
  (:use [clojure.contrib.def])
  (:import [java.util.concurrent SynchronousQueue]
	   [java.util NoSuchElementException]))
