[mercury-users] Re: question about try/2
Fergus Henderson
fjh at cs.mu.OZ.AU
Thu Nov 11 13:34:52 AEDT 1999
Hi Bart,
On 11-Nov-1999, Bart Demoen <bartd at cs.monash.edu.au> wrote:
>
> why is the mode for
>
> :- mode try(pred(out) is det, out(cannot_fail)) is cc_multi.
>
> instead of (what I expected):
>
> :- mode try(pred(out) is det, out(cannot_fail)) is det.
>
> ?
You're the second person to ask me about that today,
so I'll answer it on mercury-users.
Consider the following code:
foo :-
(
throw("this"), throw("that")
;
throw("the other")
).
Which exception will be thrown?
It depends on the order of execution.
Which exception will be caught by `try'?
Whichever one is thrown.
So in general, the results of `try' might depend
on the order of execution. In a parallel implementation
of Mercury, you might get different results each time
you run the program. Hence it must be `cc_multi'.
If you are writing code where you know that the end
result will be the same, then you can use `promise_only_solution'.
Otherwise, you should propagate `cc_multi' all the way up
the call tree, to document that the results might be different
each time.
For example, one common idiom is where you have two means of
computing a result, called `fast_but_fallible_algorithm' and
`slow_but_reliable_algorithm', both of which have the same
declarative semantics, but where `fast_but_fallible_algorithm'
will throw an exception for some inputs. In that case,
since the same answer will be computed regardless of
whether `fast_but_fallible_algorithm' throws an exception,
it is safe to use `promise_only_solution':
:- mode solve_problem(in, out) is det.
solve_problem(Inputs, Outputs) :-
Outputs = promise_only_solution(solve_problem_cc(Inputs)).
:- mode solve_problem_cc(in, out) is cc_multi.
solve_problem_cc(Inputs, Outputs) :-
try(fast_but_fallible_algorithm(Inputs), Res),
(
Res = succeeded(Outputs)
;
Res = exception(_),
slow_but_reliable_algorithm(Inputs, Outputs)
).
For more details on this general topic, see [1];
that paper is on Haskell, and the situation in Mercury
is a bit different, but many of the issues that arise are the same.
> and why is there no mode for the case that the "pred(out) is nondet"
> (for instance) ?
Use `try_all' for that case.
The reason that there is no mode for `try' for that case is that it
would be useless. Because the exception caught can depend on the
order of execution, and because it is not feasible for the compiler
to try all possible orders of execution, `try' would still have to be
`cc_multi' in that case:
:- mode try(pred(out) is nondet, out) is cc_multi.
But if `try' in this mode is cc_multi, it means that you can't backtrack
into it, so you would only ever get at most one solution of the called pred.
Given that, you might as well make the called pred `cc_nondet', since
it will often be more efficient that way.
> I remember two years ago discussing with you catch/throw in the
> context of Mercury and you said there were problems with catch/throw
> related to destructive update; these problems seem to have
> disappeared; is that because of the restriction "pred(out)" ?
Yes. The predicate called by `try' cannot do any destructive update
on variables that remain live outside of the `try'. `try' essentially
gives you full rollback transaction semantics: if an exception is
thrown, then any variables that are still in scope will have their
original values. That means that if you have a unique structure that
you want to pass to an algorithm that uses destructive update, and you
want to use `try' to catch exceptions, then you need to call `copy' to
make a fresh unique copy of the structure inside the `try', which you
can then use destructive update on to your heart's content.
[1] A semantics for imprecise exceptions.
Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, and
Fergus Henderson. In Proceedings of the 1999 ACM SIGPLAN Conference
on Programming Language Design and Implementation.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- 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