From a-doug@microsoft.com  Fri Aug 11 06:03:52 2000
Received: from mail3.microsoft.com (mail3.microsoft.com [131.107.3.123])
	by swi.psy.uva.nl (8.9.3/8.9.3) with SMTP id GAA19053
	for <prolog@swi.psy.uva.nl>; Fri, 11 Aug 2000 06:03:51 +0200 (MET DST)
Received: from 157.54.9.100 by mail3.microsoft.com (InterScan E-Mail VirusWall NT); Thu, 10 Aug 2000 20:54:10 -0700 (Pacific Daylight Time)
Received: by INET-IMC-03 with Internet Mail Service (5.5.2651.58)
	id <Q2QXLFJL>; Thu, 10 Aug 2000 20:54:10 -0700
Message-ID: <E713F2760348D211A9B600805F6FA1AB09509A9A@RED-MSG-09.itg-messaging.redmond.corp.microsoft.com>
From: "Douglas Miles (Volt Computer)" <a-doug@microsoft.com>
To: "'Richard A. O'Keefe'" <ok@atlas.otago.ac.nz>, prolog@swi.psy.uva.nl
Subject: RE: Predicate Determining the  port in which was called.
Date: Thu, 10 Aug 2000 20:54:22 -0700
X-Mailer: Internet Mail Service (5.5.2651.58)

Thank you Richard,

Ah I see now <g>.

There is no extra iterations in any of it.
 my write/1 had a textual bug :) 
(that darn text forgot to retrieve a new item after it put the other one
back)
 
what i wanted was...

    p(Goal) :-
	(   write('(call) getting oldest item in queue.\n'), fail
	;   true
	;   write('(fail) putting back as oldest in queue.\n'), fail
	),
	writeq(Goal), nl,
	call(Goal),
	(   write('(exit)\n'), fail
	;   true
	;   write('(redo) putting that oldest back in as newest then
retriving then new oldest \n'), fail
	). 

To get..

-----------------------------------------
?- member(X,[1,2,3]),p(true),X=3.
-----------------------------------------
(call) getting oldest item in queue.
true
(exit)
(redo) putting that oldest back in as newest then retriving then new oldest
(fail) putting back as oldest in queue.
(call) getting oldest item in queue.
true
(exit)
(redo) putting that oldest back in as newest then retriving then new oldest
(fail) putting back as oldest in queue.
(call) getting oldest item in queue.
true
(exit)
X = 3
Yes

Which was what I really wanted to do !

That was right on when you asked "Let's see.  What *SHOULD* it do?"

i wanted it to:
'transform the state in some way' durring a redo (stir the soup)
'have the state transformed for later' on eventual failure (maybe things
will improve later)
'have something changed with a side effect commited' on a final exit

As you mentioned it _did_do_everything_right_ and
_visited_the_correct_ports_ at the correct times

So basicly carrying this further into a customer database example..


*if* this was for a SQL interface we could done something like this...
%---------------------------Begin
Program------------------------------------------

:-dynamic(exit_hook/1).
:-dynamic(undo_hook/2).

     p(SideEffect,StartEffect,UndoEffect,ComitEffect,Label) :-
	(   handle_call(Label,StartEffect,UndoEffect), fail
	;   true
	;   handle_fail(UndoEffect,Label), fail
	),
	SideEffect, nl,
	(   handle_exit(ComitEffect), fail
	;   true
	;   handle_redo, fail
	). 


handle_call(Label,_StartEffect,_UndoEffect):-
catch(Label,_,fail),write('(call)\n'),!.
handle_call(Label,StartEffect,UndoEffect):-
write('(call)\n'),StartEffect,assert(Label),!,make_new(Label,UndoEffect).

handle_exit(ComitEffect):- exit_hook(ComitEffect),write('(exit)\n'),!.
handle_exit(ComitEffect):-
write('(exit)\n'),asserta(exit_hook(ComitEffect)),!.

handle_fail(UndoEffect,Label):-
retract(Label),write('(fail)\n'),UndoEffect,!.
handle_fail(_,_):- write('(fail)\n'),!.

handle_redo:- write('(redo)\n'),!.

handle_cleanup(Label):-write('(cleanup)\n'),retract(exit_hook(ComitEffect)),
ComitEffect,retractall(Label),!.
handle_cleanup(Label):-retract(Label),undo_hook(Label,UndoEffect),UndoEffect
,!.
handle_cleanup(_).

make_new(Label,UndoEffect):-undo_hook(Label,UndoEffect),!.
make_new(Label,UndoEffect):-assert(undo_hook(Label,UndoEffect)).

sql(X):-write(X).

%%---------------------------End Program------------------------------

With the output...

---------------------------------------------------------------------
?- member(X,[1,2,3]),p(7
		sql(['UPDATE MYTABLE SET Value=1 WHERE pkID=',X]),
		sql('CREATE TRANSACTION\n'),
		sql('ROLLBACK TRANSACTION\n'),
		sql('COMIT TRANSACTION\n'),
		have_transaction),X=1,handle_cleanup( have_transaction ).
---------------------------------------------------------------------
(call)
CREATE TRANSACTION
[UPDATE MYTABLE SET Value=1 WHERE pkID=, 1]
(exit)(cleanup)
COMIT TRANSACTION
X = 1

---------------------------------------------------------------------
?- member(X,[1,2,3]),p(
		sql(['UPDATE MYTABLE SET Value=1 WHERE pkID=',X]),
		sql('CREATE TRANSACTION\n'),
		sql('ROLLBACK TRANSACTION\n'),
		sql('COMIT TRANSACTION\n'),
		have_transaction),X=3,handle_cleanup( have_transaction ).
---------------------------------------------------------------------
(call)
CREATE TRANSACTION
[UPDATE MYTABLE SET Value=1 WHERE pkID=, 1]
(exit)(redo)(fail)
ROLLBACK TRANSACTION
(call)
CREATE TRANSACTION
[UPDATE MYTABLE SET Value=1 WHERE pkID=, 2]
(exit)(redo)(fail)
ROLLBACK TRANSACTION
(call)
CREATE TRANSACTION
[UPDATE MYTABLE SET Value=1 WHERE pkID=, 3]
(exit)(cleanup)
COMIT TRANSACTION
X = 3
Yes

---------------------------------------------------------------------
?- p(		sql(['UPDATE MYTABLE SET Value=1']),
		sql('CREATE TRANSACTION\n'),
		sql('ROLLBACK TRANSACTION\n'),
		sql('COMIT TRANSACTION\n'),
		have_transaction),true,handle_cleanup( have_transaction ). 
---------------------------------------------------------------------
(call)
CREATE TRANSACTION
[UPDATE MYTABLE SET Value=1]
(exit)(cleanup)
COMIT TRANSACTION
Yes

---------------------------------------------------------------------
?- p(		sql(['UPDATE MYTABLE SET Value=1']),
		sql('CREATE TRANSACTION\n'),
		sql('ROLLBACK TRANSACTION\n'),
		sql('COMIT TRANSACTION\n'),
		have_transaction),fail,handle_cleanup( have_transaction ).
---------------------------------------------------------------------
(call)
CREATE TRANSACTION
[UPDATE MYTABLE SET Value=1]
(exit)
(redo)
(fail)
ROLLBACK TRANSACTION


*WOW* I love prolog  :)

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

Do we have to make our programs run in a Metalevel or is there a _good_way_
to do this inline ?
I dont want to have to have a 'handle_cleanup(Label)'

-Douglas


-----Original Message-----
From: Richard A. O'Keefe [mailto:ok@atlas.otago.ac.nz]
Sent: Thursday, August 10, 2000 5:31 PM
To: Douglas Miles (Volt Computer); ok@atlas.otago.ac.nz;
prolog@swi.psy.uva.nl
Subject: RE: Predicate Determining the port in which was called.

In the four-port model, the events are

	call,(exit,redo)*,fail

With a more general model, one might have

	call,(exit,redo)*,(deterministic_exit|exit,cut|fail)

where deterministic exit means that the choice point is not kept
around any more, so the final redo,fail will be omitted, and
cut happens later, outside the goal in question, again removing
the choice point so that the final redo,fail will be omitted.

In order to support a customer's database connection scheme,
Quintus had to put in a special 'trail hook' so that clean-up
actions could be relied on even after determine exit or
subsequent cuts.  It also handled exceptions.
(I have never quite forgiven Quintus.  They never did pay me for
my shares when they were sold, and they yanked my paper on exception
handling from a conference, so that someone else got the credit for an
admittedly independent invention of it.  Nor have I forgiven the BSI
for ignoring the exception handling proposal I sent them at the end
of 1984; the so-and-sos never even gave it a document number.)

