For Programmers: Free Programming Magazines  


Home > Archive > Prolog > August 2004 > Remove all asserted facts?









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Remove all asserted facts?
news.adelphia.net

2004-08-25, 3:57 pm

I want to remove all facts that were instantiated by the assert() statement
(I want to reset the Prolog database). I tried:

retractall(_).

But I got an instantiation error. What's the most convenient way to do
this?

Thanks.


russell kym horsell

2004-08-26, 3:56 am

news.adelphia.net <no-mail-please@nospam.com> wrote:
> I want to remove all facts that were instantiated by the assert() statement
> (I want to reset the Prolog database). I tried:
> retractall(_).
> But I got an instantiation error. What's the most convenient way to do
> this?
> Thanks.


You probably need to keep track of which facts you're likely to assert
and what they look like, in order to be completely portable.

retractall/1 needs the form of the fact to be deleted. "_" isn't a term.

You could try some horrible rubbish like:

:- clause(Foo,true),
functor(Foo,F,N), functor(Bar,F,N),
retractall(Bar),
fail.

Or perhaps check whether the "dynamic" predicates of your implementation
can be queried and use that istead of clause/2 -- which will probably
delete too much.

--
kym@kym.massbus.org
SDF Public Access UNIX System - http://sdf.lonestar.org
Paul Tarau

2004-08-26, 8:58 pm

"news.adelphia.net" <no-mail-please@nospam.com> wrote in message news:<O4GdnY0PNb08MLHcRVn-oQ@adelphia.com>...
> I want to remove all facts that were instantiated by the assert() statement
> (I want to reset the Prolog database). I tried:
>
> retractall(_).
>
> But I got an instantiation error. What's the most convenient way to do
> this?
>
> Thanks.


In systems with multiple dynamic databases like BinProlog or Jinni
you can use operations like *db_clean(DataBaseName)* to achieve this
efficiently. In any case, using *abolish* is faster than *retractall*
which has to linearly scan all clauses - not a very smart thing given
that you want all of them removed! Having to keep track of your
asserted predicates is clearly no fun - you might want to use things
like *current_predicate* for doing this automatically - but again,
that
adds unpleasant complexity, performace hits and/or non-portability
to your code.

Paul Tarau

========================================
=====================
New Jinni3D Prolog toolkit with high-level agent oriented
API, supporting morphing, 3D-avatar animation, 3D-graph layout
and more - is now available from http://www.binnetcorp.com
========================================
=====================
Bart Demoen

2004-08-26, 8:58 pm

Paul Tarau wrote:

> In systems with multiple dynamic databases like BinProlog or Jinni
> you can use operations like *db_clean(DataBaseName)* to achieve this
> efficiently.


The use of db_clean/1 introduces non-portability with 100% certainty.

On the other hand, I suppose that the db_* family of predicates that
BinProlog supports can be written in ISO Prolog without any complexity
added. Maybe you can post such an implementation: I think that's what
the OP is really after.


> In any case, using *abolish* is faster than *retractall*
> which has to linearly scan all clauses - not a very smart thing given
> that you want all of them removed!


A goal like ?- retractall(foo(_)). does NOT need to linearly scan all
clauses and a decent implementation of retractall/1 should exploit this,
by doing the same action as for ?- abolish(foo/1). except forgetting
that foo/1 was ever a dynamic predicate.


> Having to keep track of your
> asserted predicates is clearly no fun - you might want to use things
> like *current_predicate* for doing this automatically - but again,
> that
> adds unpleasant complexity, performace hits and/or non-portability
> to your code.


Since current_predicate/1 is an ISO pred, I don't see how it would
introduce non-portability. (not that I think that ISO has defined
current_predicate/1 in a good way, but it is defined)

Whether its usage introduces a performance hit is another kettle of
fish, but performance hits usually come from badly implemented builtins
(rather than their nature) and/or bad program design.

Cheers

Bart Demoen
Jan Wielemaker

2004-08-26, 8:58 pm

In article <eda0377c.0408261214.2788d74@posting.google.com>, Paul Tarau wrote:
> "news.adelphia.net" <no-mail-please@nospam.com> wrote in message news:<O4GdnY0PNb08MLHcRVn-oQ@adelphia.com>...
>
> In systems with multiple dynamic databases like BinProlog or Jinni
> you can use operations like *db_clean(DataBaseName)* to achieve this
> efficiently. In any case, using *abolish* is faster than *retractall*
> which has to linearly scan all clauses - not a very smart thing given


abolish does something differently. It not only removes the clauses, but
also the dynamic aspect of the predicate. This is generally not what you
want. Actually ISO abolish/1 is pretty broken as it is not needed for
dynamic clauses and does not work on static ones. I do not see the
performance penalty. retractall/1 can check that the head is completely
unbound and in that case use the same algorithm as abolish to get rid of
the clauses (ok, this is a little bit tricky as retractall(foo(X,X))
cannot use the simple wipe-all strategy).

> that you want all of them removed! Having to keep track of your
> asserted predicates is clearly no fun - you might want to use things
> like *current_predicate* for doing this automatically - but again,
> that
> adds unpleasant complexity, performace hits and/or non-portability
> to your code.


It is a real FAQ question, but as you say there is not a very clean and
portable solution. On most systems providing modules you can easily
create something along your db_clean/1 by removing the dynamic
predicates in a certain module. The following should work for SWI-Prolog
and I think also for Quintus, SICStus, Ciao and maybe a few more.

db_clean(Module) :-
forall(predicate_property(Module:Head, dynamic),
retractall(Module:Head)).

Enjoy

--- Jan

vannoord@let.rug.nl

2004-08-26, 8:58 pm

Paul Tarau <ptarau@yahoo.com> wrote:

> In systems with multiple dynamic databases like BinProlog or Jinni
> you can use operations like *db_clean(DataBaseName)* to achieve this
> efficiently. In any case, using *abolish* is faster than *retractall*
> which has to linearly scan all clauses - not a very smart thing given
> that you want all of them removed! Having to keep track of your
> asserted predicates is clearly no fun - you might want to use things
> like *current_predicate* for doing this automatically - but again,
> that
> adds unpleasant complexity, performace hits and/or non-portability
> to your code.


i wouldn't be worried by both "complexity" and "performance hits" in
this context. And non-portability would be an issue only if there is
a portable solution.

Gj




--
Gertjan van Noord Alfa-informatica, RUG, Postbus 716, 9700 AS Groningen
vannoord at let dot rug dot nl http://www.let.rug.nl/~vannoord
russell kym horsell

2004-08-27, 3:57 am

Jan Wielemaker <jan@ct.xs4all.nl> wrote:
[...]
> abolish does something differently. It not only removes the clauses, but
> also the dynamic aspect of the predicate. This is generally not what you
> want. Actually ISO abolish/1 is pretty broken as it is not needed for

[...]

A good point. I've even noticed some retract's also do the same.
Jan Wielemaker

2004-08-27, 3:57 am

In article <cgmbdd$pnu$1@chessie.cirr.com>, russell kym horsell wrote:
> Jan Wielemaker <jan@ct.xs4all.nl> wrote:
> [...]
> [...]
>
> A good point. I've even noticed some retract's also do the same.


If the implementation claims compatibility to ISO or some de-facto
standard you should report that as a bug to the implementor.

--- Jan
Paul Tarau

2004-08-27, 3:59 pm

Bart Demoen <bmd@cs.kuleuven.ac.be> wrote in message news:<1093553411.183827@seven.kulnet.kuleuven.ac.be>...
> Paul Tarau wrote:
>
>
> Since current_predicate/1 is an ISO pred, I don't see how it would
> introduce non-portability. (not that I think that ISO has defined
> current_predicate/1 in a good way, but it is defined)
>
> Whether its usage introduces a performance hit is another kettle of
> fish, but performance hits usually come from badly implemented builtins
> (rather than their nature) and/or bad program design.
>

Paul Tarau

2004-08-27, 8:56 pm

Bart Demoen <bmd@cs.kuleuven.ac.be> wrote in message news:<1093553411.183827@seven.kulnet.kuleuven.ac.be>...
> Paul Tarau wrote:
>
>
> Since current_predicate/1 is an ISO pred, I don't see how it would
> introduce non-portability. (not that I think that ISO has defined
> current_predicate/1 in a good way, but it is defined)
>
> Whether its usage introduces a performance hit is another kettle of
> fish, but performance hits usually come from badly implemented builtins
> (rather than their nature) and/or bad program design.
>


While this is all true, the deeper problem is that the Prolog API
handling sets of clauses forming a database (also seen sometime as a
map from functor/arities to actual clause sets) has grown in a very
ad-hoc way for about 20 years or so. Just think about how easy all
this would be if you could look at Prolog sets of clauses the same way
Java programmers look at Collections and Maps. As the original poster
requested - one should be able to empty a database just by saying so -
rather than having to maze through several fairly intricate and
sometime implementation dependent builtins.

Paul Tarau

P.S. I apologize for the empty reply that might have went out before
this.
Holger Kanwischer

2004-08-28, 3:57 pm

Jan Wielemaker wrote:
> It is a real FAQ question, but as you say there is not a very clean and
> portable solution. On most systems providing modules you can easily
> create something along your db_clean/1 by removing the dynamic
> predicates in a certain module. The following should work for SWI-Prolog
> and I think also for Quintus, SICStus, Ciao and maybe a few more.
>
> db_clean(Module) :-
> forall(predicate_property(Module:Head, dynamic),
> retractall(Module:Head)).
>


Your db_clean/1 also removes imported predicates, sometimes this is not intended.
The following avoids this.

db_clean(Module) :-
forall((predicate_property(Module:Head, dynamic),
\+ predicate_property(Module:Head, imported_from(_))),
retractall(Module:Head)).


Holger
Jan Wielemaker

2004-08-30, 8:58 am

Holger,

In article <cgqjge$9e$00$1@news.t-online.com>, Holger Kanwischer wrote:
> Jan Wielemaker wrote:
>
> Your db_clean/1 also removes imported predicates, sometimes this is not intended.
> The following avoids this.
>
> db_clean(Module) :-
> forall((predicate_property(Module:Head,
dynamic),
> \+ predicate_property(Module:Head, imported_from(_))),
> retractall(Module:Head)).


I know/knew :-) I left it out for two reasons. First of all,
predicate_property/2 is supported by a number of Prolog systems,
but the imported_from(Module) property is SWI-Prolog specific and
second some people have claimed (and I agree) than exporting
dynamic predicates isn't really elegant.

Cheers --- Jan
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2009 codecomments.com