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
-~----------~----~----~----~------~----~------~--~---

Reply via email to