;;;
;;; ( with-exception-handler HANDLER THUNK )
;;;
;;; This example demonstrates a lower level procedure that I don't think would
;;; ordinarily be used. The guard macro takes care of the continuation
;;; plumbing you see here for you, ultimately doing something like this.
;;; There is also a similar 'with-exception-handlers' documented in the srfi.
(require-extension srfi-34)(call-with-current-continuation
;;; We want control to resume at k if an exception is raised, not
;;; to continue normally at the next line after the call to raise.
;;; ( raise is smart enough call error if it finds that the exception
;;; handler returns control to it instead of to another continuation as
;;; it should )
(lambda(k)(with-exception-handler;;; This is the exception handler that gets stored in
;;; in the dynamic environment. Ultimately, it passes control to
;;; k because returning is an error
(lambda(e)(display "I handled an exception: ")(write e)(newline)(display "Passing it to previous continuation")(newline)(k e));;; This is the thunk that may throw an exception
(lambda()(display "Doing more stuff")(newline)(raise 'yet-another-exception)(display "Won't get here")(newline)))))

License

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED ASIS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Modifications are copyright Ben Clark (2007), governed by the same conditions. Any errors are mine.

Requires

syntax-case

Documentation

srfi-34.egg contains the reference implementation of srfi-34 packaged as a chicken egg.

See http://srfi.schemers.org/srfi-34/srfi-34.html for additional documentation

The module maintains a list of exception handlers using dynamic-wind. It defines the default exception handler which aborts execution of the whole program, thusly:

A naked call to raise would end up calling this handler, aborting the program.

procedure: (raise OBJ)

Raise an exception. OBJ can be any scheme object. Invokes the 'current exception handler' thunk, which is the car of the *current-exception-handlers* list. This handler thunk handles the exception OBJ.

The handler thunk should then either call error to stop program execution, or it should have stored the continuation at which to resume execution of the program after handling the exception, and pass it's result to that continuation where the program's flow of execution will resume.

Installing an exception handler that returns will cause the raise procedure to abort the program by call error, alerting that the exception handler thunk erroneously returned control to the raise procedure instead of to a different continuation as it should.

macro: (guard (VAR CLAUSE1 CLAUSE2 ...) BODY )

Syntax: Each clause should have the same form as a cond clause.

Semantics: Whereas raise is analogous to the throw commonly found in other languages, guard is analogous to the try/catch syntax often implemented. VAR gets bound to the exception thrown by BODY, and then the CLAUSEs which have access to VAR, are evaluated until one of the tests succeeds, and the corresponding code gets run. As with cond, the else test always succeeds and so can be used to handle general exceptions.

Notes: guard also supports => in the clauses. If the test returns a useful value, then => can be used to specify a procedure to apply to that value in that case. See the examples section and the srfi for clarification on this.

procedure: (with-exception-handler HANDLER THUNK)

Returns the result(s) of invoking thunk. Handler must be a procedure that accepts one argument. It is installed as the current exception handler for the dynamic extent (as determined by dynamic-wind) of the invocation of thunk.