[mercury-users] exceptions and cc_multi

Paul Massey pma at miscrit.be
Wed Nov 29 21:14:39 AEDT 2000

> 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, whereas the part of the
program which is 'relatively' safe being protected by an
exception handler get marked as cc_multi (for me it's the
Map_det_update/3 which is dangerous, or some new bit of code
developed by someone else and not the try_io) ? What I need
from the try_io is to know which errors are potentially
rethrown (if any). eg.

:- module file.
:- interface.
:- import_module io.

:- pred main(io__state::di,io__state::uo) is det.

:- implementation.
:- import_module exception.
:- import_module string.
:- import_module list.

main -->

:- pred read_file(string::in,string::out,io__state::di,io__state::uo) is det.

read_file(File,Contents) -->
        ( { Res = ok(Stream) } ->
        ;     { throw("death at clients") } ).

:- pred read_contents(string::out,io__state::di,io__state::uo) is det.

read_contents(Contents) -->
	( { Res1 = ok } ->
	       { Contents = Contents0 }
	;      { throw(Res1) } ).

Now, I could change the main to being:

:- pred main(io__state::di,io__state::uo) is cc_multi.

main -->
	try_io(lambda([X::out,I::di,O::uo] is det,
	( { ResultTry = succeeded(Contents) },
	; { ResultTry = exception(_) },
	        io__format("Exception Recieved",[]) ).

Which is safe in this usage only - Does that help anyone
else who uses the read_file/4 and read_contents/3 predicates
to make their calls safe ? Is there any indicate that these
predicates are unsafe ? Not at present (in fact it's worse
than that - the predicates are labelled as det which
indicates, AFAIK, that it will always return the same result
and gives an indicate that the predicate is safe, but it
could potentially throw that exception). Labelling them as
'det' is in someways misleading ...

Catching an exception is simply a way of joining the
exception 'processing stream' with the normal program flow.
After joining the threads, the only thing relevant is
whether all the exceptions were trapped and whether the
success/exception cases were successfully dealt with. Why
should a higher level predicate be informed that an
exception was trapped (I want to know the inverse of that -
that a potential exception wasn't trapped) ?


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