[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Scheme-reports] 6.1 Exceptions needs examples
* Aaron W. Hsu [2012-03-22 17:09] writes:
>> 1. When no cond-clause matches, guard re-raises the condition in the
>> dynamic context of the guard form. This is similar to Java's
>> try-catch (+ the implicit re-throw).
> It is possible to do this with the current guard form explicitly, but it
> is not possible to go the other way easily.
>> 2. Evaluate the cond-tests in the dynamic environment of the original
>> raise. The advantage of this strategy is that it preserves the
>> context of the error; which is useful for debugging. This is
>> to Common Lisp's HANDLER-CASE.
> This is already the semantics of normal raise or raise-continuable calls
> using with-exception-handler, and thus, already provided for.
Note that I said the "cond-tests". Only the cond-tests are evaluated in
the dynamic environment of raise; the <expression>s of the matching
cond-clause are evaluated in the dynamic environment of the guard
> should not generally result in any loss of error information, and
> usually, a guard is the wrong thing to use if you intend to halt
> computation, or if you want to handle continuable notifications that
> should return to the normal flow of things. Guards are designed for
> handling the cases where an error in the computation of the body
> prevents further reasonable execution of that body, but which does not
> necessarily stop the entire computation outside of the body. The guard
> allows one to easily provide a result to the outer context in the cases
> when it may be impossible to get a reasonable result from the body form.
> This is more difficult to accomplish in a nice way using the existing
> semantics of the other forms because you would have to explicitly
> capture a continuation around the code and then use an exception handler
> that called out to the continuation to get this same behavior. Even that
> is not quite right because you do not necessarily want the dynamic
> extent of the body to pollute your response in the case where the body
> code is no longer helpful.
guard can be expressed as macro that uses with-exception-handler and
raise. See SRFI-34 for proof.
> As an example, convincing or otherwise:
> (define (notify-gui-maybe msg)
> (define (alert) (display msg) (newline))
> (guard (c [(error? c) (alert)])
> (parameterize ([current-output-port gui-output-port])
As (error? c) does not depend on the dynamic environment this would do
the same with strategy 2 from above (just more efficiently).
> Here, I am thinking of a custom output port that reports messages into a
> gui window of some application. However, there may be a problem, where
> perhaps the connection to the GUI is gone, or the window that the port
> relied on was closed by the user. We want to do the guard outside so
> that we can retry the (alert) using the normal output port, but if there
> was another message that was signalled, such as a warning, then we
> really want that to occur inside the the parameterize so that it can
> take advantage of the gui message port. Thus, this back and forth
> behavior is exactly what we want in this case. Moreover, using the guard
> form, it is very clear what we are doing here, but if I were to write
> the same thing explicitly with continuations and with-exception-handler,
> things would get very hairy very quickly. User's are likely to end up
> implementing this over and over again, because this pattern is common.
> It is better to have a common exception handling paradigm that supports
> this behavior from the start.
> I hope that this at least clarifies some of the rationale for guard.
I understand the reason to have a macro for a common use case but I
can't see why your example requires full continuations.
Scheme-reports mailing list