On Wed, Feb 25, 2009 at 12:32 PM, Chouser <[email protected]> wrote:
> On Wed, Feb 25, 2009 at 9:05 AM, Jeffrey Straszheim
> <[email protected]> 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 [email protected]
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
-~----------~----~----~----~------~----~------~--~---