Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!snorkelwacker.mit.edu!bloom-beacon!dont-send-mail-to-path-lines From: gyro@cymbal.reasoning.COM (Scott Layson Burson) Newsgroups: comp.lang.scheme Subject: REPOST : Exception handling - how to define it ? Message-ID: <9104081741.AA03393@cymbal.reasoning.com.> Date: 8 Apr 91 17:41:28 GMT References: Sender: daemon@athena.mit.edu (Mr Background) Reply-To: Gyro@reasoning.com Organization: The Internet Lines: 71 Date: 5 Apr 91 08:03:48 GMT From: Stephen J Bevan What is the general style used to write exceptions and their handlers in Scheme? By exceptions I mean facilities similar to catch/throw in Lisp. The ways I can see of doing it are :- I don't know what most people do, but: 1) Pass a success and fail continuation to every function. 2) Pass multiple continuations, one for each error to be handled. I have been curious for some time about the style that would result from passing explicit exception continuations to every function (letting the default continuation serve for the normal case). One would think that this would clutter the code unacceptably, but I wonder if there might not be some way to mitigate or manage the clutter. So I have had it in the back of my mind for some time to attempt the experiment of writing a program in this style and seeing how it worked out. How might the clutter be dealt with? Well, consider that 1) it would consist of numerous additional arguments being passed to functions, and 2) Scheme has a very powerful mechanism, viz. lambda-abstraction, for encapsulating argument passing. So, for instance, imagine that CAR took a second argument which would be invoked if the object passed to CAR were not a cons. Then one could do something like (define (foo [...args...] fail) (let ((car (lambda (x) (car x fail)))) ... (car something) ...)) (One might well prefer giving the two-argument CAR a different name, e.g., CAR-GEN, where "gen" might mean "general" and/or "generator".) Would this really work in practice, for a program of substantial size and complexity? I don't know. But perhaps you can see why I'm curious about the possibility. But I'm not really recommending this, both because it's experimental and because to do it with reasonable efficiency would probably require access to the internals of one's Scheme implementation. 3) Call a function that is assumed to be set by the user e.g. (define (foo x y z) ... (if (some-unexpected-error) (unexpected-error-exception args) ...)) where `unexpected-end-of-file-exception' as a default just aborts. It would be up the user to re-define this as appropriate. I guess the easiest way of doing this would be via fluid-let e.g. :- (fluid-let ((unexpected-error-exception (lambda x (do-something-sensible x)))) (foo an-arg another-arg yet-another-arg)) However, as fluid-let isn't part of the standard (as far as I'm aware), this solution isn't portable. This approach is equivalent to the built-in exception systems of Zetalisp and (New) Common Lisp. If you're in a situation where you need to write a Scheme program of substantial size and production quality and are willing to limit yourself to Schemes that support FLUID-LET, I would recommend you do it this way. If you can't use FLUID-LET, however, I don't know what to suggest. -- Scott