On Oct 16, 10:16 am, "Matthew D. Swank" <[EMAIL PROTECTED]>
wrote:
> So, I'm trying to clear up some flow control issues in my head, and I
> want to confirm that my thinking is at least in the right direction.
>
> Let's say I implement a very simple restart facility with the
> following style:
>
> (def current-handler)
> (def current-restart nil)
>
> In some code I want to handle I put:
>
> (binding [current-handler (fn [e] (if current-restart (current-
> restart) <some non-local exit>))]
> <stuff>)
>
> Later on in the same dynamic extent as <stuff> I put:
>
> (binding [current-restart (fn [] 42)]
> (try <dodgy-expr>
> (catch Throwable t (current-handler t))))
>
> What can <some non-local exit> be?
>
> In common lisp (if it didn't have a condition system) I could do
> something like:
> (block my-block
> (let ((*current-handler*
> (lambda (e)
> (if *current-restart* (funcall *current-restart*) (return-
> from my-block e)))))
> <stuff>))
>
> of in scheme (with fluid-let)
>
> (call/cc
> (lambda (my-esc)
> (fluid-let ((*current-handler*
> (lambda (e) (if *current-restart* (*current-
> restart*) (my-esc e)))))
> <stuff>)))
>
> Anyway you get the idea; I can unconditionally take an escape
> continuation.
>
> However, in clojure/java given:
> (binding [current-handler (fn [e] (if current-restart (current-
> restart) <some non-local exit>))]
> <stuff>)
>
> The only thing I can do for <some non-local exit> is to throw (or re-
> throw):
>
> (try (binding [current-handler (fn [e] (if current-restart (current-
> restart) (throw e)))]
> <stuff>)
>
> ;;However, even if there is something to catch it...
> (catch Throwable t <more stuff>))
>
> There is no guarantee the catch block will ever see it, and there is
> no way to unconditionally abort the rest of the computation from the
> point of <some non-local exit> to the return of <stuff>. Is that
> correct?
>
First off, catching and eating Throwable is bad practice. If your code
instead catches Exceptions, then Errors will throw through untouched.
While there is no direct here-to-there non-local flow control, one
possible mechanism is to:
Declare your own derived class of Error.
Pre-allocate an instance of it in your handler-binding mechanism,
throw that instance as some-non-local-exit, making the original
exception its cause.
Catch your derived Error type and check for that specific instance in
a try block surrounding <stuff> - if it's that instance, it's that
escape, else rethrow.
Rich
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---