Path: utzoo!utgpu!news-server.csri.toronto.edu!bonnie.concordia.ca!uunet!munnari.oz.au!goanna!ok From: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) Newsgroups: comp.lang.prolog Subject: Re: block and exit_block Message-ID: <6245@goanna.cs.rmit.oz.au> Date: 13 Jun 91 04:50:34 GMT References: <1536@quintus.UUCP> Organization: Comp Sci, RMIT, Melbourne, Australia Lines: 107 In <1536@quintus.UUCP> dave@quintus.UUCP (David Bowen) writes: > I don't know where the names came from. However, the U.S. committee (X3J17) > recommended changing them to catch and throw and this was agreed upon at the > last meeting of the ISO committee (WG17) last November. I believe the names were proposed by AFNOR. The earlier proposal (for if_error/3 and signal_error/1) failed, having had an Auckland postmark. In article , dc@dcs.qmw.ac.uk (Daniel Cohen;E303) writes: > And the latest draft of the standard ( N72 ) refers to catch and throw, so > it looks like this one has been cleared up, at least until Paris when > someone will no doubt try to change the names back again! I believe that ALS are represented on the ANSI committee, and the last time I saw a manual for ALS Prolog on the Mac it called the operations 'catch' and 'throw'. Surprise! (The "Personal" version on the PC lacks these operations.) The names are marginally better than `block' and `exit_block', but they really are not at all good. Let me start by pointing out that in Common Lisp and MIT Scheme and other modern Lisp-based systems a very sharp distinction is drawn between catch/throw and exception handling. catch/throw or escape functions (Pop2 "jumpouts") are for non-local transfers of successful control. Exception handling is for handling exceptions. An exception handler may indicate *recovery* by executing a throw (calling an escape function), but error *signalling* is most definitely *not* based on catch/throw. Indeed, my use of structured terms to represent error situtations in the Quintus design was directly inspired by the proposal which eventually became the basis of the present Common Lisp "condition" system. The parallel goes something like this: QP CLtL2 signal_exception error [p886] if_exception handler-bind [p898] [p901] There's nothing quite like CL's "restarts". Perhaps there should be. The way an interactive user can select a restart in, say, Oaklisp, is rather neat. I've tried to keep my Lisp skills reasonably current. I believe that a good AI programmer will not lock himself into one programming language, even if it is as good as Prolog, so that if he comes across an excellent program written in the "other" language he'll still be able to learn from it. I claim that my experience with Scheme and Lisp has conditioned me to expect that 'throw' is like selecting an alternative SUCCESS continuation, whereas my knowledge of exception handling systems (such as "recovery blocks" and "restarts") is that arriving in an exception handler should be like selecting an alternative FAILURE continuation. To put one consequence of this plainly, I expect that var(X), catch(*, (X=1, throw(*))) => X == 1 but that var(X), if_exception(*, (X=1, signal_exception(*)), true) => var(X) If something called catch/throw *does* undo my variable bindings, I am going to be _very_ annoyed, and I will write nasty letters to the vendor in question for providing me with a useless implementation of non-local exit. If something advertised as an exception handling mechanism *doesn't* restore my variable bindings to the state they were in before the protective was donned, I am going to be _very_ _very_ annoyed indeed, and I will demand my money back. In 1984 I proposed as a guiding principle for any Prolog standard that it should contain nothing that would _forbid_ a coroutining implementation. Frank McCabe did announce in 1985 that the BSI committee had a guiding principle: to produce a minimal standard. But the "don't kill MU Prolog" principle was not adopted. None-the- less, I still think it's a good principle. NU Prolog and other coroutining Prolog systems pose an extremely interesting question. Suppose I do signal_exception(foo(X)) at a time when X is _constrained_ (by one or more delayed goals) but not _instantiated_? *EXCEPTION* handling means that it makes no sense to continue the current conjunct, so we mustn't wake up the delayed goals. What to do? For catch/throw, because we're selecting a new continuation point in the *same* conjunct, it does make sense to continue, and we can wake up the delayed goals when we need to, but then we can't use the mechanism for recovery, and we cannot use the mechanism to abandon a computation that is known to be useless, because any amount of it could be persisting as suspensions. What to do? I'm really not sure what the "right" answer is. If someone wants to provide catch and throw in a Prolog system, the only problem is that it can't be used as an exception handling/recovery mechanism. For exception handling, The only suggestion I have is that in QP, if storage permits, signal_exception(X) and ( assert('Snark'(X), Ref), instance(Ref, 'Snark'(Y)), erase(Ref), signal_exception(Y) ) behave the same, so that signal_exception/1 in a coroutining system should treat constrained but uninstantiated variables the same way that assert/1 does (or, by a similar argument, the way write/1 does). I hope someone else has a better idea. -- Q: What should I know about quicksort? A: That it is *slow*. Q: When should I use it? A: When you have only 256 words of main storage.