 (ns conexp.contrib.generators
-  (:use [clojure.contrib.macro-utils :only (macrolet)])
   (:use [clojure.contrib.def])
   (:import [java.util.concurrent SynchronousQueue]
 	   [java.util NoSuchElementException]))

;;                  (for [i (range x)]
;;                    (yield i)))
;;                100)
;;   -> () ; or even nothing (?)
;; but this does
;;   (generate-by (fn runner [x]
;;                  (doseq [i (range x)]
;;                    (yield i)))
;;                100)
;;   -> (0 1 2 3 ...)

(set! *warn-on-reflection* true)

(defmacro make-generator
  ""
  [function]
  `(fn [& args#]
     (let [#^SynchronousQueue queue# (SynchronousQueue.),

    (runner)))

(defmacro generate-by
  "Colletcs all values \"yield\"ed by the function. The definition of
  function may use the special function \"yield\" with an additional
  argument. All these values are than collected into a lazy sequence.

  Example:

    (generate-by (fn [x]
                   (doseq [i (range x)]
                     (yield i)))
                 5)

    -> (0 1 2 3 4)

  Note that you have to call yield explicitly. When you wrap a call to
  yield into a lazy sequence this call may not be done at all. For example

    (generate-by (fn [x]
                   (for [i (range x)]
                     (yield i)))
                 5)

    -> ()"
  [function & args]
  `(generate ((make-generator ~function) ~@args)))


;; Coroutines



nil
