🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.prolog
Article #4085

Re: retractall and backtracking

#4085
From: Joaquim Baptista (pxQuim)
Date: Fri, 09 Jun 1989 19:41
101 lines
4149 bytes
In article <575@hfserver.hfnet.bt.co.uk> nigel@hfserver.hfnet.bt.co.uk (Nigel Cliffe) writes:
>
>   I have a problem with backtracking, and retracts that don't appear to
>   happen - here is a simplified example:
>
>   If I have a database with repeated facts in it and want to a) get just the
>   unique entries, and b) retract the contents of the database as I get those
>   entries then one way that ought to work is this:
>
>   :- dynamic foo/1.
>   foo(bar1).
>   foo(bar1).
>   foo(bar2).
>
>   write_unique_foos :-
>	   foo(X),
>	   write(X),nl,
>	   retractall(foo(X)),
>	   fail.
>
>   Now if the predicate "write_unique_foos" is called, then I get all three
>   values for foo written, not just the two unique ones as I would expect.
>   However if I trace the execution, and test the contents of the database at
>   various points from the debugger then "foo(bar1)" has disappeared after the
>   first call to "retractall".
>
>   Can anyone explain why this happens.
>
>      I know that I can get the result I want by using setof, and probably 
>   hundreds of other methods as well, I'm just curious as to why things don't
>   behave as I would expect.
>
>   Just incase this is system dependent, I'm using Quintus 2.4 on a Sun3 running
>   Sun OS 3.5.
>

This problem is a feature rather than a bug, and occurs because of the
usual implementations for the prolog interpreters.

When one calls one predicate, as you did in foo(X), a "frame" is
pushed onto the stack. The actual formats of this frame differ, so I
will have to simplify it a little. Anyway, this frame will have
information about the first clause foo(bar1), and will know that, on
failure, it should try the second foo(bar2). This "will know that" is
just a pointer for the second clause.

Now, when you retractall(foo(X)), both clauses will go away, but the
pointer to the second stored in the frame will not. That is why your
program, in backtracking, will still find the second clause. Note that
if you had...

	foo(bar1)
	foo(bar2)
	foo(bar1)

...then your program probabily would run as you expected.

Variations on this problem also arise with asserta and assertz, as in:

/* this will write 1 and fail */
	a(1).
	exec1:- a(X), write(X), asserta(a(X)), fail.

/* this will loop forever, exhausting your heap space,
   writing 1211111111... */
	b(1). b(2).
	exec2:- b(X), write(X), assertz(b(X)), fail.

/* this will do one of the above, depending on your system.
   Tail recursion optimization will make it do as exec1; else it will
   do as exec2. */
	c(1).
	exec3:- c(X), write(X), assertz(c(X)), fail.

One way to solve your problem is not to depend on backtracking, as in:

	:- dynamic foo/1.   /* I've never seen one of this, but I guess
				what it does. */
	foo(bar1).
	foo(bar2).
	foo(bar3).

	write_unique_foos :-
		foo(X),
		write(X), nl,
		retractall(foo(X)),
		write_unique_foos.

This works in all the interpreters and compilers I know of (more or
less dinamic foo/1 :-).

Hope this enlightened you. Feel free to write.
--
--------

Joaquim Manuel Soares Baptista    | BITNET/Internet: px@fctunl.rccn.pt
Centro de Inteligencia Artificial | UUCP: px@unl.uucp
Uninova                           | ARPA: px%fctunl.rccn.pt@mitvma.mit.edu
Fac. de Ciencias e Tecnologia/UNL | PSI/VMS: PSI%(+2680)005010310::PX
2825 Monte de Caparica            | Fax:   (+351) (1) 295 4461
PORTUGAL                          | Sound: (+351) (1) 295 4464 ext. 1360
Technical Details
Message-ID: <PX.89Jun9194119@uniq.unl.fctunl.rccn.pt>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!ames!lll-winken!uunet!mcvax!inesc!unl!uniq!px
References: <575@hfserver.hfnet.bt.co.uk>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!ames!lll-winken!uunet!mcvax!inesc!unl!uniq!px
From: px@unl.fctunl.rccn.pt (Joaquim Baptista (pxQuim))
Newsgroups: comp.lang.prolog
Subject: Re: retractall and backtracking
Message-ID: <PX.89Jun9194119@uniq.unl.fctunl.rccn.pt>
Date: 9 Jun 89 19:41:19 GMT
References: <575@hfserver.hfnet.bt.co.uk>
Sender: px@unl.fctunl.rccn.pt
Organization: Universidade Nova de Lisboa, Portugal
Lines: 101
In-reply-to: nigel@hfserver.hfnet.bt.co.uk's message of 8 Jun 89 08:07:02 GMT
Posting-Front-End: GNU Emacs 18.44.13 of Wed Jun 24 1987 on uniq (berkeley-unix)