🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.prolog
Article #1030

Re: Novice RETRACT question

#1030
From: Richard A. O'Keefe
Date: Tue, 31 Jul 1990 07:01
97 lines
3630 bytes
In article <1939@engage.enet.dec.com>, ssmith@ncdel.enet.dec.com (Sheldon E. Smith) writes:
> What I'd *really* like is a book of Prolog
> algorithms, but I'll defer *that* to another article.
(Hmm.  What would you pay for it?  What do you want to be in it?)

> In any event, I have facts of the form
> 	object(Time,X,Y)
> where X and Y are locations, and Time is the time-stamp when the object
> was observed.  That is, given the facts
> 	object(1,12,34).
> 	object(2,12,34).
> 	object(3,12,34).
> I'd like to retract "object(1,12,34)" and "object(2,12,34)".

This is where data base references come in extremely handy, if
your Prolog system supports them.  Suppose you want to retract
everything before a particular Time:

	retract_objects_before(Time) :-
		forall((
		    clause(object(T,_,_), _, Ref),
		    T < Time
		), (
		    erase(Ref)
		)).

If your Prolog lacks the forall/2 structure, you might do

	retract_objects_before(Time) :-
		\+ (
		    clause(object(T,_,_), _, Ref),
		    T < Time,
		    \+ erase(Ref)
		).

which comes to the same thing.  (The jargon for this kind of structure
is a ``failure-driven loop''.)

Something marginally cleaner employs an auxiliary predicate:

	erase_refs([]).
	erase_refs([Ref|Refs]) :-
		erase(Ref),
		erase_refs(Refs).

which you only have to write once, and then uses a call to setof/3:

	retract_objects_before(Time) :-
		setof(Ref,
		    X^Y^B^( clause(object(T,X,Y), B, Ref), T < Time ),
		    Refs),
		erase_refs(Refs).

Another approach might be to write an erase_all/2 looking rather like
findall/3 but erasing things instead of returning them.  (Algol 60
fans:  do you recognise Jensen's device?)

	erase_all(Ref, Generator) :-
		forall(Generator, erase(Ref)).

and then call

	erase_all(Ref, /* where */
		( clause(object(T,_,_), _, Ref), T < Time ))

> I'd have thought that something like
> reduce_objects :- object(I,X,Y),object(J,X,Y),
> 		I < J,
> 		retract(object(I,X,Y)).

> What am I doing wrong?

Not a lot, actually, except for ugly layout.  The main problem
is that retract/1 removes *ONE* clause each time it succeeds; here
you want to remove ALL the old clauses.  Your code could be
reshaped a bit to

	retract_old_objects :-
		object(J, X, Y),	% for each timestamped object
		object(I, X, Y),	% for each object at that same place
		I < J,			% if I is older than J
		retract(object(I,X,Y),	% delete it
		fail			% and look for some more
	    ;	true.			% succeed when we've run out.

I'm a wee bit unhappy about this.  Surely an object ought to have an
identity of its own, other than its location at some time.  How do you
say that the object which is at (27,33) at time 98 is the same object
as the object which is at (28,32) at time 99?

A rule of thumb for checking that your program makes sense is that
whenever you have a call to retract/1
    - either it is in a loop
    - or you have identified a UNIQUE clause you want to remove
-- 
Science is all about asking the right questions.  | ok@goanna.cs.rmit.oz.au
I'm afraid you just asked one of the wrong ones.  | (quote from Playfair)
Technical Details
Message-ID: <3493@goanna.cs.rmit.oz.au>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rutgers!tut.cis.ohio-state.edu!pacific.mps.ohio-state.edu!zaphod.mps.ohio-state.edu!samsung!munnari.oz.au!bruce!goanna!ok
References: <1939@engage.enet.dec.com>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rutgers!tut.cis.ohio-state.edu!pacific.mps.ohio-state.edu!zaphod.mps.ohio-state.edu!samsung!munnari.oz.au!bruce!goanna!ok
From: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe)
Newsgroups: comp.lang.prolog
Subject: Re: Novice RETRACT question
Message-ID: <3493@goanna.cs.rmit.oz.au>
Date: 31 Jul 90 07:01:36 GMT
References: <1939@engage.enet.dec.com>
Organization: Comp Sci, RMIT, Melbourne, Australia
Lines: 97