[mercury-users] exceptions and cc_multi

Fergus Henderson fjh at cs.mu.OZ.AU
Thu Nov 30 16:59:27 AEDT 2000


On 30-Nov-2000, Michael Day <mikeday at corplink.com.au> wrote:
> 
> > It would be OK to use `promise_only_solution' here, provided that
> > `risky_operation' is det or semidet (not cc_multi or cc_nondet),
> > and that `do something impure' and `undo the impure thing' are both det.
> 
> Right. However, I can't seem to use promise_only_solution, as
> risky_operation returns a unique io__state, which appears to mess things
> up (the error messages are fairly impenetrable).

That's a good point.  It's possible to define a `promise_only_solution_io'
that works like `promise_only_solution' but which also handles I/O
procedures or other procedures with di/uo modes.

	% `promise_only_solution_io' is like `promise_only_solution',
	% but for procedures with unique modes (e.g. those that do IO).
	% 
	% A call to `promise_only_solution_io(P, X, IO0, IO)'
	% constitutes a promise on the part of the caller that for
	% the given IO0, there is only one value of `X' and `IO0' for
	% which P(X, IO0, IO) is true.  `promise_only_solution_io(P,
	% X, IO0, IO)' presumes that this assumption is satisfied, and
	% returns the X and IO for which `Pred(X, IO0, IO)' is true.
	% 
	% Note that misuse of this predicate may lead to unsound
	% results: if the assumption is not satisfied, the behaviour
	% is undefined.  (If you lie to the compiler, the compiler
	% will get its revenge!)

	:- pred promise_only_solution_io(pred(T, IO, IO), T, IO, IO).
	:- mode promise_only_solution_io(pred(out, di, uo) is cc_multi,
			out, di, uo) is det.

This can be implemented using a fairly simple hack:

	promise_only_solution_io(Pred, X) -->
		call(cc_cast_io(Pred), X).

	:- func cc_cast_io(pred(T, IO, IO)) = pred(T, IO, IO).
	:- mode cc_cast_io(pred(out, di, uo) is cc_multi) =
		out(pred(out, di, uo) is det) is det.

	:- pragma c_code(cc_cast_io(X :: (pred(out, di, uo) is cc_multi)) =
				(Y :: out(pred(out, di, uo) is det)),
			[will_not_call_mercury, thread_safe],
			"Y = X;").

I think this is a good candidate for inclusion in the standard library.

> > Proof:
> 
> <snipped>
> 
> That's a very clear proof. However... does the same proof apply for
> try_io?

No, it doesn't.  For `try_io', the final io__state is unspecified, and
in general can have more than one possible value.  The "risky_operation"
might be something like

	risky_operation -->
		print("Hello,\n"),
		{ more_risky_stuff },
		print("world!\n").

	more_risk_stuff :-
		throw("oops!").

and the compiler could potentially move the call to risk_stuff before
the call to `print("Hello,\n")' or after the call to `print("World\n")',
or run it in parallel with either of those.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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