[mercury-users] exceptions and cc_multi

Mark Anthony BROWN dougl at cs.mu.OZ.AU
Thu Nov 30 16:08:25 AEDT 2000


Paul Massey writes:
> 
> > 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) ?

It would be a mistake to think that `det' and `cc_multi' are giving
you information regarding exceptions.  They give you information about
failures and successes, but they don't say anything about termination
(abnormal or otherwise).

 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 -->
>      read_file("file",Contents),
>      io__write(Contents).
> 
> :- pred read_file(string::in,string::out,io__state::di,io__state::uo) is det.
> 
> read_file(File,Contents) -->
>         io__open_input(File,Res),
>         ( { Res = ok(Stream) } ->
> 	      io__set_input_stream(Stream,Orig),
> 	      read_contents(Contents),
> 	      io__set_input_stream(Orig,_),
> 	      io__close_input(Stream)
>         ;     { throw("death at clients") } ).
> 
> :- pred read_contents(string::out,io__state::di,io__state::uo) is det.
> 
> read_contents(Contents) -->
> 	io__read_file_as_string(Res1,Contents0),
> 	( { 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,
> 		      read_file("file",X,I,O)),ResultTry),
> 	( { ResultTry = succeeded(Contents) },
> 	        io__write(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 ?

Apart from the fact that the body contains a call to `throw', no.
Perhaps a comment would help?  ;-)

> 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) ?

Because there may have been more than one potential exception, and
the Mercury implementation may have (operationally) chosen one of
them.  In code that handles exceptions, it is possible that different
exceptions lead to different solutions, so the Mercury implementation
may effectively be making a choice between two different solutions in
the higher level predicate.  This is (declaratively) modelled using
committed choice nondeterminism.

Hope this clarifies things,
Mark.

--------------------------------------------------------------------------
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