Re: suspending until several variables are all instantiated

From: <wh_at_icparc.ic.ac.uk>
Date: Tue 06 Sep 2005 07:30:30 PM GMT
Message-ID: <20050906193029.GF8558@tempest.icparc.ic.ac.uk>
Andy,

Thanks for writing such a detailed response!  I'd just like to add a couple
of things:

On Mon, Sep 05, 2005 at 06:17:05PM +0100, Andrew Eremin wrote:
> Version 5.8 #82, Wed Feb 16 00:08 2005
> [eclipse 1]: [user].
>  my_plus(A,B,C) :-
>     ( var(A) ->
>         % B must have been instantiated to cause this waking

This is not strictly true, and it should be considered bad coding practice
to assume that the suspension condition has been satisfied just because the
goal has been woken - always check the condition if you really need it to be
true.  In this case the code following the comment doesn't assume B is
instantiated, so there's no problem.

>         suspend(my_plus(A, B, C), 1, A->inst)

Please don't use priority 1 for general-purpose suspensions.  That's way too
high.  In general, you should use 3 or below (4, 5, ...).  Use priority 2
only for "I really want this to happen as soon as possible and in particular
before all the normal constraints get woken".  Using priority 1 will
likely just confuse you because, for instance, the debugging tools could
display out-of-date information.  Many libraries also run segments of code
at priority 2 in order to say "please don't interrupt this" - if you have
goals suspended at priority 1, these can interrupt that code, with
unpredictable results.

>     ; var(B) ->
>         % A must have been instantiated to cause this waking
>         suspend(my_plus(A, B, C), 1, B->inst)
>     ;
>         C is A + B
>     ).
>            user       compiled traceable 536 bytes in 0.00 seconds
> 
> Yes (0.00s cpu)
> [eclipse 2]: suspend(my_plus(A, B, C), 1, [A, B]->inst).

Note that my_plus need not be suspended on both A and B - one is sufficient.
For example, if you suspend on A and meanwhile B gets instantiated, you
don't care, since you still have to wait for A to be instantiated anyway (in
fact, you've saved some work).

To generalise this, the following (untested :) code will wait for a list of
variables to become ground and then call the supplied goal:

wait_for_list([], Goal) :-
	call(Goal).
wait_for_list([X | List], Goal) :-
	( var(X) ->
	    suspend(wait_for_list([X | List], Goal), 3, X->inst)
	;
	    wait_for_list(List, Goal)
	).

Cheers,
Warwick
Received on Tue Sep 06 20:32:54 2005

This archive was generated by hypermail 2.1.8 : Wed 16 Nov 2005 06:07:39 PM GMT GMT