Subject: RE: Predicate Determining the port in which was called.

From: "Douglas Miles (Volt Computer)" <[email-masked]>
Date: Fri, 11 Aug 2000 02:57:27 -0700

> On Fri, 11 Aug 2000,  Jan Wielemaker wrote:
> > On Fri, 11 Aug 2000,  Douglas Miles (Volt Computer) wrote:
> 
> >
> >Thats very iteresting about the 
> >
> >"call,(exit,redo)*,(deterministic_exit|exit,cut|fail)"
> >
> >So there are 3 unique finishing states?
> >
> >* deterministic_exit
> >* exit,cut
> >* fail
> 
> Actually 4: there are also exceptions.  In addition, deterministic
> exit is a bit vague as sometimes non-deterministic exit could actually
> have been deterministic, but Prolog may fail to see it (either because
> it doesn't look at exclusive cases or because hashing yields the same
> key for two values of the first argument that are actually
> different).
> 
> Altogether, call and fail are easy, and so are exceptions.
> 
> With some extremely dirty hacking using prolog_current_frame/1 and
> prolog_frame_attribute/3 you can at runtime find out about Prolog's
> notion of the last choice-point.  This is highly non-portable.

When I very first sent mail on this topic, I thought the first advice I'd
recieve
was going to involve: prolog_current_frame/1 and prolog_frame_attribute/3.
If you feel it is a resonable idea for now, i am game and not affraid of
non-portiblity.

> You can find out about being cut in a foreign predicate, but currently
> not in a pure Prolog predicate.  Unfortunately, a call to a foreign
> predicate can only initiate and complete a query back to Prolog. 
> I.e. it is not possible to write call/1 as a foreign predicate keeping the
> non-deterministic behaviour of the argument and monitoring the ports.
> If you want to give up non-determinism that is a simple way to realise
> a good clean interface.
> 
> I've seen various proposals around to deal with these issues.  I'm
> in favour of something along these lines
> 
> 	guard(Goal, Event, Guard)
> 
> Where, if Event is unified to the event (call, redo, fail, exit,
> deterministic_exit, cut, exception(Exception)) Guard will be
> called.

I do like the guard/3 actually I really like it, especially since you are
supporting deterministic_exit, cut, exit with failure and a unifiable
exception handler.

> 
> Should deterministic_exit be the sequence exit, cut?
> 

Logicly I'd think it could be.  (seems the programmer could have volentarily
put a cut on the edge of a deterministic exit and )  would we always
understand an deterministic_exit if it is broken into two separate events or
would be shown only as one event or perhaps still two:  exit, (cut |
deterministic_exit)

Richard is definately better to answer this.  

> How should bindings and exit status of the guards be handled? 
> Best might be to undo bindings, ignore success/failure and
> force them to be deterministic.  Only exceptions of the guards
> should have effect (so a DB commit from the cut guard raising
> an exception will force the whole to exit with an exception). 	

Well the guards usually only need to react to the events in a deterministic
manner. since they seem to be wrapping an interface most of the time and
will do the exception handling privately.  It would be nice thought to be
able to change the outcomes or guard your guards.

> This seems to fit nicely with catch/3.  Not really thought of
> it in detail, but I my first guess is it should be feasible 
> to implement
> this without too much trouble and without performance degradation.
> 
> Another issue is that you may wish to handle bindings of the call
> guard in the others (like the transaction id).  You could still
> trick that using
> 
> 	make_transaction(Transaction),
> 	guard(Goal, Event, my_guard(Event, Transaction)),
> 	...
> 
> my_guard(call, _).
> my_guard(fail, Transaction) :-
> 	<rollback>.
> ...
> 
> 
> Not really clean, but acceptable, I would say.
> 
> 	Regards --- Jan
> 

gosh Labeling :)
 
could make_transaction(+) generate information for tracking our state in its
output term? Might let us locate and change guard infomation?

make_transaction(Transaction), 
	(guard(Goal, Event, my_guard(Event, Transaction))...))
	;
	(
	change_tracking_schema(Transaction,TransactionMetaChanges),
	guard(Goal, Event, my_guard(Event, TransactionMetaChanges))...
	),

my_guard(call, _).
my_guard(fail, Transaction):-
		(<rollback>) ; 
	
(change_tracking_schema(Transaction,TransactionMetaChanges)
			my_guard(Event, TransactionMetaChanges))
		
-Douglas