I've got this narrowed down to what seems an interaction issue between macros and closures in lazy-seq. Run this code:
(defn gen-lazy []
(let [coll [1 2 3]]
(lazy-seq
(when-let [s (seq coll)]
(throw (Exception.))
)
)
)
)
(def lazy (gen-lazy))
(try
(println "lazy:" lazy)
(catch Exception ex
(println ex))
)
(try
(println "lazy, again:" lazy)
(catch Exception ex
(println ex))
)
... and explain to me what you see there. The first time, exception, the second time, empty list.
Now if you either a) remove the let statement and put the sequence [1 2 3] directly into where it says coll then it "works" = same exception in both cases.
(defn gen-lazy []
(lazy-seq
(when-let [s (seq [1 2 3])]
(throw (Exception.))
)
)
)
Or if you take out the when-let macro it works, too:
(defn gen-lazy []
(let [coll [1 2 3]]
(lazy-seq
(seq coll)
(throw (Exception.))
)
)
)
Only the combination of closure + when-let macro breaks thigs. I know clojure does some funky things to closures in lazy-seq (see "... perform closed-over local clearing on the tail call of their body" on this page:
http://clojure.org/lazy), this is related to the undocumented :once keyword on function calls. Maybe that interferes with macros? Or maybe I'm barking up the wrong tree.
-- hank