🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.prolog
Article #3556

Re: The double-cut (long)

#3556
From: Jonas Nygren
Date: Mon, 08 Aug 1988 16:27
160 lines
5237 bytes

In a previous article I suggested a new language primitive for Prolog,
the double-cut with the following semantics:

               a :- b, c, !!, d, e.
			   
    to achieve the equivalence of:
	
            a :- b, c, !, d, !, e, !.
 
 Below are most of the comments, in short, I recieved, followed by a 
 final comment from me where I try to state my case.
 
-------------

            2   are there any Prolog-variants with similar functionality?
 
From: "Brad Miller" <miller@ACORN.CS.ROCHESTER.EDU>
>From the RHET user manual (tr 238, university of rochester)
  
\hornfnitem{And*}{$<$Form$>$*}{New\\Current Status: Untested} A macro form
for \HC{AND [CUT] Form1 [CUT] Form2 \ldots [CUT] FormN}. That is, any
backtracking\index{backtracking}\ needed at all inside of the AND* causes it
to fail.

------------------ 
From: Peter Reintjes <pbr@mcnc.org>

............ It is almost never
necessary -- no that is too mild -- it is never *necessary* 
< -- to have more than one cut per clause -- >,
and you are right that it looks messy.
 
Richard O'Keefe has written a very good little paper on
the correct use of cuts. ..........

-----------

>From: ok@quintus.uucp (Richard A. O'Keefe)
 
Forgive me, but I cannot imagine this cropping up.  Why do you WANT to
prevent backtracking over system-calls?  You can backtrack over read/1,
write/1, var/1, assert/1 &c all you like, it doesn't hurt.  As a general
rule, code with side-effects should be determinate, so backtracking over
it will do nothing at all.  (retract/1 is an exception, but I doubt that
anyone would commend as an example to follow.)
 
Please let's see a real example of where you think you need to do this.

>> SEE example below!

 ----
 
>From: gooley@s.cs.uiuc.edu

Some debuggers on some systems (C-Prolog is one, I think) show apparent
retries of deterministic system calls.  Might this be misleading people
into thinking that cuts are needed to prevent such retries in actual
execution?

---------

>From: lang@zeta.PRC.Unisys.COM (Francois-Michel Lang)
 
This could also be a "problem" for when debuggers show apparent
retries of deterministic user-defined predicates.
 
	<-- examples -->
 
In the second example, it looks like the cut has saved some work,
whereas it really hasn't.

---------

My comments to the response :

Well somebody else have had the same thought (rochester above) before me and
I still have to wait for an original idea. The reason behind the double-cut
suggestion wasn't performance and it wasn't induced by trace or debug output.
Rather it was triggered by the code I had to construct in order to make my
program work correct.

Instead of inventing my own example I choose to base it on an example most of
you have seen, the reconsult example in Clocksin & Mellish. I have done some
smaller modifictions to the code. After this follows the same example
but with the use of the double-cut. 

myreconsult(File) :-
	retractall(done(_)),
	assert(done(1)),
	seeing(Old),
	see(File),
	repeat,
	read(Term),
	try(Term),
	seen,
	see(Old),
	!.

try(X) :- is_eof, !.
try((?- ...Goals)) :- !, do_call(Goals), fail.
try(Clause) :- 
	head(Clause,Head),
	record_done(Head),
	assertz(Clause),
	fail.

do_call([]) :- !.
do_call([G|Goals]) :- call(G), do_call(Goals), !.

record_done(Head) :- done(Head), !.
record_done(Head) :-
	functor(Head,Func,Arity),
	functor(Proc,Func,Arity),
	asserta(done(Proc)),
	retractall(Proc),
	!.
	
head((A:-B), A) :- !.
head(A,A).

The cuts in 'do_call','record_done' and 'head' are due to the fail in 'try' 
which means that the complexity of 'try' (2nd & 3rd clause) has propagated to 
their subgoals. Using the doubel-cut as proposed would allow us to limit
the complexity to the clause where it arises:

dc_try(X) :- is_eof, !!.   % Just for symmetry
dc_try((?- Goals)) :- !!, dc_do_call(Goals), fail. 
dc_try(Clause) :- !!,
	dc_head(Clause,Head),
	dc_record_done(Head), 
	assertz(Clause), 
	fail.

dc_do_call([]).
dc_do_call([G|Goals]) :- call(G), dc_do_call(Goals).

dc_record_done(Head) :- done(Head).
dc_record_done(Head) :-
	functor(Head,Func,Arity),
	functor(Proc,Func,Arity),
	asserta(done(Proc)),
	retractall(Proc).
	
dc_head((A :- ...B), A).
dc_head(A,A).


In this code no cuts are needed in 'dc_do_call', 'dc_record_done' or
'dc_head' and the fail-complexity is totally contained in 'dc_try'. 
Mr O'Keefe it's not a question of necessity but of beauty and functionality.
In the last example the number of cuts has actually diminished with use of 
the double-cut and the code is 'cleaner' and easier to understand, I believe.

I don't know if I have been able to show how the double-cut could benefit
Prolog but I will not carry my 'campaign' further, this is my last entry on
the double-cut.

Jonas Nygren
Technical Details
Message-ID: <1164@ttds.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!attcan!uunet!mcvax!enea!kth!draken!ttds!jonasn

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!attcan!uunet!mcvax!enea!kth!draken!ttds!jonasn
From: jonasn@ttds.UUCP (Jonas Nygren)
Newsgroups: comp.lang.prolog
Subject: Re: The double-cut (long)
Message-ID: <1164@ttds.UUCP>
Date: 8 Aug 88 16:27:40 GMT
Reply-To: jonasn@ttds.UUCP (Jonas Nygren)
Organization: The Royal Inst. of Techn., Stockholm
Lines: 160