Subject: Re: Condition/Exception Handling
From: (Rob Warnock)
Date: 1996/10/01
Newsgroups: comp.lang.scheme
Message-ID: <52qlm4$>

Malcolm Chan Chiang Yoeng <> wrote:
| A program I'm writing needs the ability to handle exceptions that may
| be generated in the course of its execution.  Having had some Common
| Lisp experience, I realise that CL can handle this, in the form of
| conditions.  What is the Scheme analogue of this?  Is it a feature
| that's available on common implementations, say, SCM?

Since exception handling as such is not part of the formal Scheme
standard(s), facilities vary widely among implementations. However,
the infamous "June 92 Meeting" [see the Scheme archives] ratified
(for R5RS, if it ever...) a mechanism that was already implemented
in many Scheme dialects (including SCM and MzScheme) called "dynamic-wind",
which is a lot like CL's "unwind-protect" except that all the args
are thunks (rather than forms), and there is an additional "pre-entry"
case which is needed since the main body might be re-entered using
a captured continuation. The form is:

	(dynamic-wind thunk1 thunk2 thunk3)

First "thunk1" is called, then "thunk2" is called, then "thunk3" is called,
and the normal value of the "unwind-protect" is the value of "thunk2".

However, the execution of "thunk2" is protected against non-local exit
*and* re-entry. "Thunk1" is guaranteed to be executed before "thunk2"
is (re)entered, and "thunk3" is guaranteed to be executed before "thunk2"
is (re)exited -- no matter how many times entry/exit occurs. A coding
pattern I've seen used (for an "unwind-protect" sort of behavior) is:

(let ((done #f))
  (call/cc		; or call/ce, if you prefer it (and have it)
    (lambda (k)
	(lambda () (set! done #f))
	(lambda () (...whatever you want protected...) (set! done #t))
	(lambda () (if (not done)
		       ...whatever cleanup you need to do...
		       (k ...whatever you want the fail-value to be...))))))))

[Caveat: For MzScheme (but not SCM), you also need to (set! done #t) in
the "cleanup" before calling the exit continuation, otherwise it loops
forever because "thunk3" gets re-entered *again* on the way out. But
I can't really complain. The June 92 meeting explicitly left unspecified
the semantics of invoking a continuation while in "thunk3". (*sigh*)]

I used patterns similar to the above when writing a shell-style Scheme
REPL [TBA "soon"] that is portable between SCM & MzScheme (at least).
Routines named "eval-safely/apply-safely/read-safely" let me (re)capture
control in the event of user syntactic or semantic errors.

If you're looking for something with more "built-in stuff" than just
dynamic-wind, MzScheme *also* has a complete-separate and particularly
fine-grained exception-handling mechanism, which the author says is the
one "proposed by Friedman, Haynes, and Dybvig". Click on "Exceptions" in:


Rob Warnock, 7U-550
Silicon Graphics, Inc.
2011 N. Shoreline Blvd.		Phone: 415-933-1673  FAX: 415-933-0979
Mountain View, CA  94043	PP-ASEL-IA