-
Notifications
You must be signed in to change notification settings - Fork 6
try
This (a-sync try) library file provides a 'try' macro for dealing with exceptions.
(try body0 body1 ... (except condition cond-clause0 cond-clause1 ...))
Try is a macro used in the implementation of the event loop provided by this library, and is exported in case it is useful to users. The macro has two keywords, 'try' and 'except'. It executes the body clauses, and if an exception is raised by them passes control to the 'except' block with 'condition' set to the condition which was raised. The cond-clauses are then evaluated as if in a cond expression. If a cond test is found to be true, or there is none found to be true but there is an else clause, then the relevant cond consequent or else clause will be evaluated and returned. If none of the cond tests in the cond-clauses is found to be true and there is no else clause, the exception condition will be re-raised as if by raise, for a dynamically enclosing try form, guard form or with-exception-handler form (if any) to handle.
The return value of try, if there is no exception raised by the body clauses or any exception raised is handled by a cond-clause, is the value of the last expression of the body clauses or of the cond-clause, as the case may be.
This is similar to but not the same as the R6RS 'guard' form. The guard form has the property that the cond tests and any cond consequent or else clause are evaluated in the dynamic environment of the call to 'guard', and if no cond test is found to be true and there is no else clause, there is a return to the dynamic environment in which the exception arose for the exception condition to be re-raised with raise-continuable (the use of raise-continuable is to allow continuable exceptions to propagate successfully through the 'guard' form). However, this can result in triggering multiple dynamic unwinds and rewinds. As mentioned, the 'try' form always re-raises with 'raise' (so in effect converting any continuable exception to a non-continuable one). Furthermore it only exits the dynamic environment in which the exception occurred once. Prior to version 0.24 of this library it did this by evaluating the cond tests, and any cond consequent or else clause, or re-raising the exception, in the dynamic environment of the original call to 'try'. From version 0.24 the cond tests are evaluated, and any re-raising of the exception occurs, in the dynamic environment in which the exception arose, and only the cond consequent (upon a test succeeding) or else clause is evaluated in the dynamic environment of the call to 'try'. This change is to avoid losing relevant debugging information should the exception be re-raised, but in the highly unlikely event that user code which applies this macro has a cond test which accesses parameter values set by parameterize in the 'try' body clauses, it could change the behavior of the cond test. If so, checkout try.ss for version 0.23 and use that (and have a little less debugability): either version of try.ss will work fine with this library.
Put another way, the 'try' macro behaves like a conventional stack unwinding exception implementation. 'guard' does not necessarily do so.
Continuable exceptions with generalised handling forms such as 'guard' are generally to be avoided, as they may break any intermediate resource management which uses rethrows or dynamic winds. Continuable exceptions are also usually unsuitable for use with asynchronous event handlers, which is why the 'try' form is used in the implementation of the event loop provided by this library. But for cases where that is not true and you know what you are doing, you can use 'guard' instead of 'try' for maintaining continuable exceptions as continuable.
The 'try' macro is first available in version 0.3 of this library.
Here is an example of the use of try:
(display (try (display "In outer try form\n")
(try (display "In inner try form\n")
(raise 'five)
(except c
[(eq? c 'six) 6]))
(except c
[(eq? c 'five) 5])))
Library files:
- (a-sync coroutines)
- (a-sync event-loop)
- (a-sync thread-pool)
- (a-sync compose)
- (a-sync meeting)
- (a-sync try)
Other: