Path: news.daimi.aau.dk!news.uni-c.dk!newsfeed.sunet.se!news00.sunet.se!sunic!news.sprintlink.net!news.up.net!news.mtu.edu!msunews!agate!howland.reston.ans.net!tank.news.pipex.net!pipex!dispatch.news.demon.net!demon!sunsite.doc.ic.ac.uk!yama.mcc.ac.uk!news.salford.ac.uk!aber!not-for-mail From: pcg@aber.ac.uk (Piercarlo Grandi) Newsgroups: comp.object,comp.lang.eiffel,comp.lang.c++,comp.lang.beta,comp.lang.java,comp.lang.sather Subject: Re: What Should An Exception Handling Do? -- Clarification of rules Date: 09 Apr 1996 19:34:02 +0100 Organization: Prifysgol Cymru, Aberystwyth Lines: 150 Sender: pcg@osfb.aber.ac.uk Message-ID: References: <4irn11$7ln@mimas.brunel.ac.uk> <4j03p4$fbt@hoho.quake.net> <4jqjvg$d9@glympton.airtime.co.uk> Reply-To: pcg@aber.ac.uk (Piercarlo Grandi) NNTP-Posting-Host: osfb.aber.ac.uk In-reply-to: wysiwyg@glympton.airtime.co.uk's message of 2 Apr 1996 08:11:44 +0100 X-Newsreader: Gnus v5.0.15 Xref: news.daimi.aau.dk comp.object:53965 comp.lang.eiffel:22721 comp.lang.c++:177781 comp.lang.beta:10719 comp.lang.java:32793 comp.lang.sather:12432 >>> On 2 Apr 1996 08:11:44 +0100, wysiwyg@glympton.airtime.co.uk (Adam L >>> Rice) said: pcg> The exception facility of e.g. C++ is merely a (rather ad-hoc and pcg> opaque) way of allowing the definition of what are in effect pcg> dynamically scoped procedure names, forcibly coupled with non-local pcg> control transfer. wysiwyg> So, let me see if I've understood. What you're basically saying wysiwyg> is that instead of doing (in Java): wysiwyg> try { wysiwyg> sock = new Socket("wallawalla.mit.edu", 3456); wysiwyg> } catch (IOException e) { wysiwyg> ... // handle the exception wysiwyg> } wysiwyg> ... // use the socket wysiwyg> we should do something like: wysiwyg> if (Socket.ConnectWillWork("wallawalla.mit.edu", 3456) { wysiwyg> sock = new Socket("wallawalla.mit.edu", 3456); wysiwyg> ... // use the socket wysiwyg> } else { wysiwyg> ... // handle the exception wysiwyg> } wysiwyg> Hmmmm... that's a lovely code style! I think we can call this techique wysiwyg> 'APIx2', for obvious reasons. wysiwyg> But I'm not entirely clear, it might be you were saying we should do: wysiwyg> sock = new Socket("wallawalla.mit.edu", 3456, new CantConnectHandler()); wysiwyg> if (!CantConnectHandler.ConnectFailed) { wysiwyg> ... // use the socket wysiwyg> } You are making all this up, and stupidly too, for neither of the examples you provide are anywhere similar to the ones I have given (for the ones I have given are examples of how things would look like at the place where the exception is *raised*, while your examples are about the place where it is *detected*), and neither exhibits dynamically scoped procedure names or non local control transfers, which are part of my definition. Amazing ability to misread! (and yes, I apologize if what I wrote was opaque, but I think I was darn well unambiguous). Perhaps you should reread more carefully what I have written, and perhaps refresh your memory on the notions of dynamic scoping and non local control transfer and how they look like. To help you see the light, here is your example: wysiwyg> try { wysiwyg> sock = new Socket("wallawalla.mit.edu", 3456); wysiwyg> } catch (IOException e) { wysiwyg> ... // handle the exception wysiwyg> } wysiwyg> ... // use the socket rewritten using something less ``ad hoc'' than 'try', and with dynamic scoping and non local control transfer as I had written: jmp_buf bailOutTo; static void localHandler(IOException e) { .... // handle the ``exception'' longjmp(bailOutTo); } void try() { dynamic void (*IOExceptionHandler)(IOException) = localHandler; sock = new Socket("wallawalla.mit.edu", 3456); .... // use the socket } where presumably 'bailOutTo' is initialized to some recovery point somewhere. 'dynamic' would be new storage class, much like 'extern', but with dynamic scoping within blocks. The 'Socket' constructor would contain some bit of code like: dynamic void (*IOExceptionHandler)(IOException) = DefaultHandler; Socket::Socket(String s,int p) { .... if (nogood) { // we call the user's routine, equivalent to a 'raise' (*IOExceptionHandler)(new IOException(....)); abort(); } .... } Naturally one would write it a bit better, but I have written it this way to show the parallel between the 'try' construction and the more linear one based on dynamic scoping and non local control transfers. BTW, this style of ``exception handling'' has been rather the norm in Lisp/Scheme for the past few dozen years, and could be added to C++/Java/whatever in an afternoon (indeed 'dynamic' can be _simulated_ tolerably well by a few lines of macros in C++). Dynamic scoping is useful BTW not just for providing ``exception handling'', but for a number of other uses, all those like ``exception handling'' where code semantics must depend on the dynamic context and not the static context, for example when there are runtime parameters. Currently this must be inelegantly simulated with idioms like: SomeType GlobalParameter = defaultValue; .... { SomeType savedGlobal = GlobalParameter; GlobalParameter = localValue; .... GlobalParameter = savedGlobal; } which if of course nothing but a manual (and hazardous) implementation of dynamic scoping for GlobalParameter, and that is seen rather often in C and C++ programs, instead of: SomeType Parameter = defaultValue; .... { dynamic SomeType Parameter = localValue; .... } BTW, I really hate ``exception handling'', for in cases like say 0/0 there is not exception, jsut the inability to prescribe a particular semantics statically. I think that something like ``deferred semantics'' would be a much more descriptive title. PS instead of 'dynamic' I think that 'extern auto' would be OK, and rather descriptive too, too bad that a C/C++ declaration can only have one storage class specifier.