# Assertion Creep

**URL:** <https://swi-prolog.discourse.group/t/assertion-creep/3356>\
**Category:** Help!\
**Created:** [December 9, 2020, 7:29pm UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356 "2020-12-09T19:29:35Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![edsolem](https://avatars.discourse-cdn.com/v4/letter/e/e9a140/32.png) [@edsolem](https://swi-prolog.discourse.group/u/edsolem)\
**Post date:** [December 9, 2020, 7:29pm UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/1 "2020-12-09T19:29:35Z")

</div>

I’m using: SWI-Prolog version 8.3.8

I use a `concurrent_forall` to search for solutions. When one is found, I use `assertz(result(S)` to store it. After the concurrent piece, I use a sequential `forall` to write each result to disc. When I’m done, I retract it all for cleanup. But, it doesn’t clean up. If I run the program again, the output contains the original solutions and a duplicate. The next time there are two duplicates, etc. I have to exit Prolog and restart in order to get only the output I want. Deleting the output file before re-running does not help.

```prolog
parallel(Puzzle, Scope):-
    retractall(result/1),
    rules(Puzzle, [Rule1|Rules]),
    concurrent_forall(generate(Puzzle, Rule1, Sequence), test(Puzzle, Rules, Sequence, Scope)),
    forall(result(S), wrt_nl(S, Puzzle, tw)),
    retractall(result/1).

test(_, [], Sequence, _):-
% write(Sequence).
    assertz(result(Sequence)).

test(_, [Scope|_], Sequence, Scope):-
    assertz(result(Sequence)).

test(Puzzle, [Rule|Rules], Sequence, Scope):-
    plb(Puzzle, Lock, Bond),
    check_rule(Puzzle, Rule, Sequence, Lock, Bond, Rule_Flag),
    Rule_Flag = true_flag,
    test(Puzzle, Rules, Sequence, Scope).

test(Puzzle, [Rule|_], Sequence, _):-
    plb(Puzzle, Lock, Bond),
    check_rule(Puzzle, Rule, Sequence, Lock, Bond, Rule_Flag),
    dif(Rule_Flag, true_flag).

```

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [December 9, 2020, 7:39pm UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/2 "2020-12-09T19:39:57Z")

</div>

You are calling `retractall/1` incorrectly. See the docs. You are doing:

```
retractall(result/1).

```

but you should have done:

```
retractall(result(_)).
```

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [December 9, 2020, 7:48pm UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/3 "2020-12-09T19:48:57Z")

</div>

> [@edsolem](#):
>
> `retractall(result/1)`

This should be `retractall(result(_))`.  
See the documentation for retractall/1: All facts or clauses in the database for which the _head_ unifies with _Head_ are removed.  
`result/1` doesn’t unify with `result(foo)`.

---

<div class="post-metadata">

**Author:** ![edsolem](https://avatars.discourse-cdn.com/v4/letter/e/e9a140/32.png) [@edsolem](https://swi-prolog.discourse.group/u/edsolem)\
**Post date:** [December 9, 2020, 11:28pm UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/4 "2020-12-09T23:28:22Z")

</div>

Thanks much for both replies. It’s quite clear now that I see it. I think the use of the word all in the name, combined with the \_ in the argument looked like a “double inclusive” to me. And yes, I had looked at the documentation of retractall/1. But I hadn’t looked up the precise meaning of “the Head unifies with the head”.

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [December 10, 2020, 6:32am UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/5 "2020-12-10T06:32:59Z")

</div>

> [@edsolem](#):
>
> But I hadn’t looked up the precise meaning of “the Head unifies with the head”.

Yes. So this is how you can use this in practice, for the next person who might be wondering:

```prolog
?- forall(member(X-Y, [a-1, b-2, a-3, b-4]), assertz(result(X, Y))).
true.

?- listing(result/2).
:- dynamic result/2.

result(a, 1).
result(b, 2).
result(a, 3).
result(b, 4).

true.

?- retractall(result(a, _)).
true.

?- listing(result/2).
:- dynamic result/2.

result(b, 2).
result(b, 4).

true.

```

This is _almost_ visible in the user comments under the docs for retractall/1, but I agree that the examples there don’t make this immediately obvious.

There is another catch: retractall/1 does implicitly declare its argument as a dynamic predicate, as you see from the example above. _However_, the SWI-Prolog compiler will _sometimes_ complain if the dynamic predicate is used in the source code and you don’t explicitly declare it with `dynamic`.

With this file, called `dynamic.pl`:

```prolog
run(List, Y) :-
    retractall(foo(_)),
    forall(member(X, List), assertz(foo(X))),
    bar(Y).

bar(X) :-
    foo(X).

```

It works as intended but running make/0 issues a warning:

```prolog
?- [dynamic].
true. % Everything is OK

?- make.
Warning: The predicates below are not defined. If these are defined
Warning: at runtime using assert/1, use :- dynamic Name/Arity.
Warning: 
Warning: foo/1, which is referenced by
Warning: dynamic.pl:7:4: 1-st clause of bar/1
true.

?- run([a,b,c], X).
X = a ;
X = b ;
X = c.

```

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [December 10, 2020, 8:04am UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/6 "2020-12-10T08:04:32Z")

</div>

Ideally `retractall(p/1)` should raise a type error, but it is in the end legal as it is legal to have a predicate (/)/2, e.g.

```
?- assertz(p/1).
?- p/1.
true,
?- retractall(p/1).
?- p/1.
false,

```

We have seen similar confusion before. Would it be an idea to reserve the (/)/2 such that we can raise errors when a head term is expected and a _/_ term is given? Note that reserving is nothing new: all ISO predicates are _reserved_ in the sense that the user cannot create predicates with the same name.

**edit** Thanks to @jamesnvc auto-linking, we see that (/)/2 is actually a predicate used by library(yall). That changes the discussion a bit. We would for example like to raise an error on `predicate_property(p/1, P)`, but this would disable reasoning about library yall. In itself this is not a big deal, but it is a hard to explain exception.

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [December 10, 2020, 12:17pm UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/7 "2020-12-10T12:17:30Z")

</div>

Alternatively, a pair of examples and a warning in the docs? I can volunteer to write a couple of sentences and two small examples as higher up in the thread.

But then, I wouldn’t know what to say about the warning that pops up with make/0. Or is that irrelevant.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [December 10, 2020, 4:18pm UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/8 "2020-12-10T16:18:03Z")

</div>

> [@Boris](#):
>
> Alternatively, a pair of examples and a warning in the docs? I can volunteer to write a couple of sentences and two small examples as higher up in the thread.

The question on how to document this keeps popping up. I guess we all agree that examples are the way to go. The question is how though. We to do with a number of related predicates: dynamic/1, assert/1 and some queries. Do we show these as a program? Interactive might be more helpful, but than the dynamic/1 directive is a strange beast (it isn’t always needed, but adding it to the example shows good style). If we have this example, we better link it from all involved predicates.

One option could be to have a whole lot of examples written as markdown and stored somewhere. The manual would parse the code in all examples and link or include it it from all involved predicates. For example, we could host that as a wiki on Discourse and link it automatically from the online manual. That doesn’t sound overly complicated to realize. Would it work to get a whole lot of community examples and keep everything manageable?

> [@Boris](#):
>
> I wouldn’t know what to say about the warning that pops up with [make/0](https://www.swi-prolog.org/pldoc/doc_for?object=make/0)

In theory, library(check) could do type and mode checks on arguments that are already specified in the source code. Might be a good idea. Type checking 0.0 🙂

---

<div class="post-metadata">

**Author:** ![edsolem](https://avatars.discourse-cdn.com/v4/letter/e/e9a140/32.png) [@edsolem](https://swi-prolog.discourse.group/u/edsolem)\
**Post date:** [December 11, 2020, 1:16am UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/9 "2020-12-11T01:16:56Z")

</div>

It looks like I set off more of a discussion than I had anticipated. There is a nice example in the manual for retract/1. A similar example for retractall/1 would certainly solve the problem for me. I still would not understand, however, why there is both a retract and a retractall. Intuitively, it seems that simply using retract with an anonymous variable like “retract(result(_))" would serve the same purpose as "retractall(result(_))”. I’m sure I’m missing something here, but the manual doesn’t make it clear to me.

It seems I misspoke regarding unification. It is certainly true that result/1 does not unify with result(foo). It is also true that result/1 does unify with result1, since they are the same thing. The problem is that the nature of head (with lower case h) is not obvious. I’m sure that if I read the manual from cover to cover and knew all the proper definitions by heart there would be no problem, but I’m afraid I’m just not up to that.  
FYI, I took one course in logic programming (under Leon Sterling) in 1989, and haven’t had a chance to use it until now.  
Thanks again for the help from all of you.

---

<div class="post-metadata">

**Author:** ![edsolem](https://avatars.discourse-cdn.com/v4/letter/e/e9a140/32.png) [@edsolem](https://swi-prolog.discourse.group/u/edsolem)\
**Post date:** [December 11, 2020, 1:20am UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/10 "2020-12-11T01:20:26Z")

</div>

Note there are two instances (not instantiations) in my previous reply where and underscore was not printed between two parentheses. The argument in both cases for result, should read result(\_), not result(). I’m not sure why it came out funny. If it still is wrong after I enter this reply, think of it as result(underscore). Sorry for any confusion.

---

<div class="post-metadata">

**Author:** ![edsolem](https://avatars.discourse-cdn.com/v4/letter/e/e9a140/32.png) [@edsolem](https://swi-prolog.discourse.group/u/edsolem)\
**Post date:** [December 11, 2020, 1:23am UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/11 "2020-12-11T01:23:33Z")

</div>

Oops, one more typo. I meant to say result/1 unifies with result/1 since they are the same thing. I’ll try to do a better job of proof reading my posts.

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [December 11, 2020, 6:36am UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/12 "2020-12-11T06:36:29Z")

</div>

Are you using email or are you using the website at [https://swi-prolog.discourse.group](https://swi-prolog.discourse.group)?

If you are using the website to read and post, you can edit your posts. There should be a “pencil” icon in the bottom of your own posts; click it and you can edit it to get rid of typos.

The site uses some markdown. This means that _italics_ are done using `_underscores on both sides_` of whatever you are writing. If you want to type in verbatim, you can put backticks on both sides:

```nohighlight
This is some text and `this will be printed verbatim`.

```

This way your underscores won’t get swallowed by the markdown processor.

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [December 11, 2020, 6:57am UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/13 "2020-12-11T06:57:28Z")

</div>

Sorry for the long post, don’t have time for a short one.

> [@jan](#):
>
> One option could be to have a whole lot of examples written as markdown and stored somewhere. The manual would parse the code in all examples and link or include it it from all involved predicates. For example, we could host that as a wiki on [Discourse](https://www.discourse.org) and link it automatically from the online manual. That doesn’t sound overly complicated to realize. Would it work to get a whole lot of community examples and keep everything manageable?

It is difficult to cater to everyone’s tastes I guess. I would assume that some really just go to [www.swi-prolog.org](http://www.swi-prolog.org) and read the docs, as it is supposed to be the ultimate source. Others would just google things and use stackoverflow or the search functionality of this discourse.

My _personal preference_ would be to have mini-tutorials that are prominently linked from the docs. They can live in their own space on the [swi-prolog.org](http://swi-prolog.org) site but are linked from all relevant predicate docs. You have already done that for many topics, one prominent example is [“How to create a web service easily”](https://www.swi-prolog.org/howto/http/) (very informative and useful, btw!).

The point here is that you have full control over the content _and_ there is no risk that a change of the business model of Discourse for example would force you to somehow move whatever has collected over the years. But maybe I am just paranoid.

On the topic of content for the howtos, I would say that there is a wealth of examples here as well as on stackoverflow. However, the stackoverflow stuff is sometimes quite biased, depending on who wrote it and at what stage of their Prolog journey they did it. I am also not absolutely sure about the legal aspects of just copying stuff from stackoverflow. At the moment at least I consider my own (somewhat dated) contributions on stackoverflow as an utter waste of my time.

Furthermore, some ideas from what I have seen over the years. “The C Programming Language” book is a masterpiece IMHO because through well-chosen problems and solutions it contains a nice collection of “this is how you do that thing in C”.

The C++ books written by good old Bjarne Stroustrup are interesting because he shows not only how to use a library feature but also shows how it is implemented. “The Craft of Prolog” by Richard O’Keefe is similar in spirit, but it is a dead tree book, it is not available online, and its age might be scary to the younger audience. There is a wealth of such examples in the SWI-Prolog library as well, they are just not annotated and linked as prominently as they could be.

[“The Python Tutorial”](https://docs.python.org/3/tutorial/index.html) is IMHO a killer feature of the Python language because it is gives the programmer a thing to read through once and just start writing useful programs, and also serves as a starting place for exploring the standard library.

Just some thoughts. I think I have expressed the same views before. I have tried more than once to somehow salvage the effort I put into writing stackoverflow answers by organizing it into a “Tutorial” but I always end up thinking “I just don’t know enough to write something truly useful”.

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [December 11, 2020, 7:13am UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/14 "2020-12-11T07:13:44Z")

</div>

The main difference between `retract/1` and `retractall/1` is that the argument of `retract/1` has to match the whole rule and not only the head. On the other hand you have `abolish/1` but you can’t use it to selectively retract from the database, it just completely wipes out a predicate _using its predicate indicator_.

All these things make more sense if you read once through the [Glossary of Terms](https://www.swi-prolog.org/pldoc/man?section=glossary). What is a predicate, a rule, a fact, a predicate indicator, the rule’s head and body and so on.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [December 11, 2020, 8:13am UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/15 "2020-12-11T08:13:30Z")

</div>

> [@Boris](#):
>
> don’t have time for a short one

🙂 Thanks for the answer. I largely agree. Seems we mostly agree it would be a good idea to have examples as stand alone entities and have them linked (probably automatically). The point is a bit how to get these examples and where to store them. Well, as long as they are markdown I don’t care too much where they are stored. We could use Discourse. It has an API, so we can easily get the stuff out of there and store it elsewhere. Even if there is no instance we can download the SQL database and I’m sure it isn’t too hard to get the examples out of that. We could also opt for a git repository.

Ideally examples come from real professionals. You seem to agree most people are not born as professional Prolog programmer though 🙂 I think we need something more community driven.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [December 11, 2020, 8:22am UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/16 "2020-12-11T08:22:19Z")

</div>

> [@Boris](#):
>
> On the other hand you have `abolish/1` but you can’t use it to selectively retract from the database, it just completely wipes out a predicate _using its predicate indicator_ .

ISO abolish/1 is mistake. It can only abolish _dynamic_ predicates for which we already have retract/1 and retractall/1 and then the predicate looses its (dynamic) property. Originally, abolish/1 in most systems was intended to get rid of and (including _static_) code and be able to replace it at runtime. That makes more sense, but of course not all compilation models are compatible with this idea. ISO should simply have dropped abolish/1.

Note that retractall/1 using a is\_most\_general\_term/1 _Head_ is detected and results in a quick wipe of all clauses without actually matching the heads.

---

<div class="post-metadata">

**Author:** ![infogulch](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/infogulch/32/765_2.png) [@infogulch](https://swi-prolog.discourse.group/u/infogulch)\
**Post date:** [December 16, 2020, 3:49am UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/17 "2020-12-16T03:49:52Z")

</div>

Not to derail further, but would this be a good use case for the new(ish) [isolated transactions](https://swi-prolog.discourse.group/t/first-attempt-at-isolated-transactions/2607)? E.g. `snapshot/1`:

> [snapshot/1](https://www.swi-prolog.org/pldoc/doc_for?object=snapshot/1) allows a thread to examine a frozen state of the dynamic predicates and/or make isolated modifications without affecting other threads and without making permanent changes to the database.

It seems that this is what OP _really_ wants: if they edit the original tests to assert new types of results (say, `result2(_)` for simplicity) then they would have to make sure that all the retractions are updated to match, whereas if they do it in a snapshot they can throw away the intermediate state after they’re done without worrying about other ways the database could have been side-effected. Yes?

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [December 16, 2020, 8:08am UTC](https://swi-prolog.discourse.group/t/assertion-creep/3356/18 "2020-12-16T08:08:44Z")

</div>

> [@infogulch](#):
>
> Yes?

I fear _no_ 🙂 The OP uses assert/retract to communicate between threads while snapshot/1 isolates threads ☹ (well, actually 🙂 as that is why we have snapshots). In general, snapshot/1 is a good idea to run algorithms that use the dynamic database as it both provides isolation (and thus ensures the code is thread safe) and ensures the database is unchanged at the end. This is a quite elegant alternative to the more conventional thread\_local/1 and setup\_call\_cleanup/3 approach.
