[mercury-users] exceptions and cc_multi

Renaud Paquay at MC rpa at miscrit.be
Sat Dec 2 01:46:20 AEDT 2000

Fergus Henderson wrote:
> On 29-Nov-2000, Paul Massey <pma at miscrit.be> wrote:
> >
> > > From: Fergus Henderson <fjh at cs.mu.OZ.AU>
> > >   On 29-Nov-2000, Michael Day <mikeday at corplink.com.au> wrote:
> > >   >
> > >   > Why are try and try_io both cc_multi,
> > >
> > >   Because the result depends not only on the value of the
> > >   higher-order argument, but also on how the compiler
> > >   chooses to evaluate that argument.  For example, you
> > >   could call some code that could get two different
> > >   exceptions depending on the order of execution,
> > >   e.g. `throw(1), throw(2)'.  Or you could call code that
> > >   might or might not throw an exception, depending on the
> > >   order of execution e.g. `throw(1), fail'.
> >
> > I've been wondering about this and whether the semantic
> > niceties are really that relevant in this case.
> >
> > In the server we've been developing some of the more
> > annoying problems are a result of an exception being thrown
> > in a part of the code considered as being (exception) safe.
> >
> > The information regarding exceptions seems to be at
> > completely the wrong place. For example, Map__det_update/3
> > is marked as being 'det' when it could potentially throw an
> > exception and break my code/server,
> map__det_update should never throw an exception, because you should
> never call it with arguments that would cause it to throw an
> exception.  If you ever call map__det_update with arguments that cause
> it to throw an exception, that is a bug in your code.
> In general, you should never write programs that rely on catching
> `software_error' exceptions.  Instead, you should make sure that the
> conditions that would cause such exceptions to be thrown never occur.
> Of course, everyone makes mistakes, and it is desirable for programs
> to be robust enough that they can recover from such bugs and
> continue operating anyway (after having logged the problem).
> That's why error/1 throws an exception and why we let you catch such
> exceptions.  However, that should only be used as a fall-back; you
> should never write code that deliberately relies on this.
> Note that in general *any* recursive predicate could have a bug in it
> that causes it to go into an infinite loop, and the runtime system
> could detect that and throw an exception.  Similarly, any predicate
> call might run out of stack space (or some other resource), and the
> runtime system could detect that and throw an exception.  Our current
> implementation doesn't do that, but this would certainly be allowed by
> the Mercury language specification, and would be helpful, since it
> would let you write more robust programs that recover from those errors.

I totally agree that a Mercury implementation needs to take exception
into account, and use them for, at least, all "low-level technical 
problem" (out of memory, out of any resource), because that is needed
for the type of application we write (multi-user application server):
We simply cannot "bomb out" when an "out of memory" condition occurs.

So, if I understand you well, that means, with an "exception safe" 
implementation of Mercury, all predicates will be "cc_multi" (since
any predicate could throw an exception), and "det" won't
exist anymore (except for the trivial "true", I suppose).

So, why don't we redefine the semantics of "det" and get rid
of "cc_multi"?

> So as far as exceptions are concerned there is really nothing more
> dangerous about predicates that can call error/1 than there is about
> predicates which might loop or predicates which use stack space.  It
> would be pointless to annotate `map__det_update' with something saying
> that it might throw an exception, since we'd then have to put the same
> annotation on *every* procedure.
> For this reason, adding exception specification declarations
> for things like map__det_update would not be very useful.
> Note that in this respect the exceptions thrown by map__det_update are
> qualitatively different than the ones thrown by e.g. io__write_string.
> It *is* OK to write programs that sometimes throw `io_error' exceptions.
> So, you might argue that we should extend Mercury to allow exception
> specification declarations, and use them for things like `io__write_string'.

I totally agree. In Java (sorry for this :-), there are two types of
exceptions: "Throwable", which do not need explicit annotation and
handling, and "Error", which needs explicit handling or annotation.
(I'm not sure about the class names, but that's the idea).

I've not really made my mind if this is really helpful, or a pain,
because I've not much experience with it. My feeling is that most
exception do not need to be explicitely specified, because there 
is often not much you can do about an exception, except trying to 
rollback what your program just did and report the error to a log 
and/or a user, or rollbak and rethrow to an outer handler.

However, there may be cases where explicit exception specification
might be useful, i.e. when implementing "high-level business 
processes", it may be a good idea to specify the fact that a 
predicate throws an exception when rules may not be computed, or 
something similar.

However, in such cases, it may also be as practical as defining the
computation result as a "maybe" type or "ok/error" union type.

> However, there are technical difficulties with exception specifications
> for higher-order predicates and for type class methods.
> Futhermore, using exception specifications like that would negate one
> of the key advantages of having exceptions in the first place.
> The nice thing about exceptions is that they let you decouple
> the middle-level code from all considerations of error handling.
> Only the bottom-level code which throws the exception and the
> top-level code which catches the exception need to know about it.
> This is nice, because it makes code reuser easier.
> With type classes, I can develop a whole infrastucture of
> middle-level code, and you can come along and call my infrastructure,
> plug in your own bottom-level code in a type class instance
> declaration.
> Using statically enforced or even dynamically enforced exception
> specifications would break this style of code, because in this style
> of code the middle-level code does not know which exceptions the
> low-level code throws.  Enforced exception specifications would thus
> make code reuse a lot more difficult.

I totally agree with the code reuse point, except of course, as I 
just wrote, when it may sometimes be worth considering 
exception specification as part of the signature of a predicate.

Another problem I have with Mercury exception is they are of any 
type. That is excactly the same problem as with C++: it is almost 
impossible to write a "generic" exception handler, because the set 
of exception types changes depending on what libraries are 
(directly or indirectly) used. So, having exception of any type is 
also a "break" the code re-use (in the exception handler, 
in that case).

I like the idea of Java (sorry again) of having a root 
exception class, with at least a "Message" member. That forces 
the programmer to add a message whenever he throws an exception. 
When debugging a server, that is really a good thing to have 
a message written by the programmer, because it is supposed to 
describe what exactly happened. Note that it can be done without
an explicit message, but that means 10 programmers will throw
10 different types of exceptions, and most of them won't even
bother adding an descriptive error message in it.

However, this issue is less a problem with Mercury, because 
it is always possible to get the textual representation 
of any term (using the term module, if I remember well).
We could anyway define an exception as a typeclass with a 
"get_message" predicate, and enforcing any "throw" predicate 
to throw a instance of the "exception" (or derived) typeclass.

Renaud Paquay
Mission Critical

PS: I know it is probably a sin to use "Java" in a Mercury 
    mailing list. I tend not to like that language that much, 
    but I think the exception specification of the language 
    is a nice try. The specifiers tried to make it 
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe

More information about the users mailing list