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
On Monday, 3 December 2012 00:58:08 UTC+11, Hank wrote:
>
> I'm mapping a function that throws an exception over a collection:
>
> => (def mapped (map (fn [_] (throw (Exception.))) [1 2 3]))
> #'user/mapped
>
> 'map' is lazy so we're not expecting to see the exception until we're
> trying to access the result:
> => mapped
> Exception user/fn--709 (NO_SOURCE_FILE:1)
>
> All good, let's do that again:
> => mapped
> ()
>
> Whoops! Is this by design? Why? Where does that empty sequence come from?
>
> 'map' is really just calling the lazy-seq macro but doing this with lazy
> seq works just fine:
> => (def lazy (lazy-seq (throw (Exception.))))
> #'user/lazy
> => lazy
> Exception user/fn--733 (NO_SOURCE_FILE:1)
> => lazy
> Exception user/fn--733 (NO_SOURCE_FILE:1)
>
> Same exception over and over again as it should be. I stared at the
> implementations of 'map' and lazy-seq/LazySeq for some hours but I really
> can't see it.
>
> Cheers
> -- hank
>
>
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en