Awesome!  Thanks.

And I can't think of a better way.  This is ultimately the same problem
found in this sort of code:

(let [something-we-need-to-close (open whatever)]
   (try (something-lazy something-we-need-to-close)
     (finally (close something-we-need-to-close))))

This was discussed recently on another thread, but I forget which.

On Wed, Feb 25, 2009 at 9:26 PM, Chouser <chou...@gmail.com> wrote:

>
> On Wed, Feb 25, 2009 at 12:32 PM, Chouser <chou...@gmail.com> wrote:
> > On Wed, Feb 25, 2009 at 9:05 AM, Jeffrey Straszheim
> > <straszheimjeff...@gmail.com> wrote:
> >> Does the stuff in error kit work across thread boundaries.  I'm
> thinking,
> >> for instance, if you run a computation using pmap, the individual
> >> computations are run inside of Java futures, which will propagate
> exceptions
> >> back to the caller when the caller gets the value.  So, pmap should work
> >> fairly transparently with regard to Java exception semantics.  That is
> nice.
> >
> > That's a very interesting scenario, thanks for bringing it up.
> >
> >> Can the same be said for the error-kit stuff?
> >
> > Currently, no.  The problem is that though future propagates
> > exceptions on the way out, it does not propagate dynamic binding
> > context on the way in, which is what error-kit needs to do what it
> > does.  Also, error-kit uses some thread-local data to pass information
> > up the stack past frames that don't know about it.
>
> I've got a solution or at least a sort of work-around for this.  As of
> svn 530, error-kit provides a 'rebind-fn' function  You can pass it a
> function definition and it will stuff the dynamic context needed by
> error-kit (via lexicals) into the given fn and re-dynamically-bind
> them there.  This along with some other adjustments to how error-kit
> communicates with itself across stack frames allows for this:
>
>  (with-handler
>    (doall
>      (pmap (rebind-fn
>              #(if (< % 5)
>                 %
>                 (raise *error* "foo")))
>            (range 10)))
>    (handle *error* [msg]
>      (str "caught " msg)))
>
> That returns "caught foo".
>
> The two key pieces there are the 'doall' and 'rebind-fn'.
>
> Leaving out both the 'doall' and 'rebind-fn' would mean that pmap may
> not raise the error until after leaving the dynamic scope of the
> with-handler.  The 'raise' would not see the with-handler, and throw a
> normal Java Exception, producing the same results as you'd get from
> using try/catch in a similar way:
>
>  java.lang.Exception: foo
>
> Including the 'doall' but leaving out 'rebind-fn' would still prevent
> 'raise' from seeing that its inside a with-handler, and so would still
> throw a normal Java Exception, which the with-handler would decline to
> catch:
>
>  java.lang.RuntimeException: java.util.concurrent.ExecutionException:
> java.lang.Exception: foo (NO_SOURCE_FILE:0)
>
> Leaving out the 'doall' but including 'rebind-fn' produces the
> strangest result.  The 'rebind-fn' would allow 'raise' to see the
> with-handler context, but which would no longer be in place when the
> 'raise' actually executes.  This allows error-kit's internal exception
> object to sneak out into the light of day:
>
>  Error Kit Control Exception: default, {:args ("caught foo"), :hfunc
> #<user$eval__1897$fn__1901 user$eval__1897$fn__1...@1a791f>, :blockid
> G__1899, :htag clojure.contrib.error-kit/*error*, :rfunc
> #<core$identity__3483 clojure.core$identity__3...@c3e967>}
>
> Scary, right?  So don't do that.
>
> If you correctly use 'rebind-fn' in contexts that are forced while
> still within the appropriate with-handler context, you can use the
> full power of error-kit, including continue, continue-with,
> bind-continue, etc:
>
>  (defn whine []
>    (raise *error* "whine"))
>
>  (with-handler
>    (doall
>      (pmap (rebind-fn
>              #(with-handler
>                 (if (< % 5) % (whine))
>                 (bind-continue insert [x] x)))
>            (range 10)))
>    (handle *error* [msg]
>      (continue insert (str "caught " msg))))
>
> If anyone is still reading and has a better idea for how to get
> try/catch and dynamic binding contexts to stay in sync, I'm all ears.
>
> --Chouser
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to