Are predicates (at the toplevel or even defined in files) by default dynamic?

Just running:

Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.32-10-g1885b056f)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
 
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
 
?- assertz(tryit(alpha,beta)).
true.
 
?- tryit(A,B).
A = alpha,
B = beta.

I was not expecting this to work without a dynamic/1 statement.

Similarly, loading a file with

a(A,B) :- assertz(tryit(alpha,beta)),tryit(A,B).

No problem!

?- [test].
true.

?- a(X,Y).
X = alpha,
Y = beta.

In the “Database” section in the manual, it says:

Dynamic predicates are predicates for which the list of clauses is modified at runtime using asserta/1, assertz/1, retract/1 or retractall/1.

The way that I understand this is that using any of these means that the predicate is, indeed, dynamic. In particular, for retractall/1, it says:

If Head refers to a predicate that is not defined, it is implicitly created as a dynamic predicate.

If you hover on footnote 80 in the docs for retractall/1 it also says,

The ISO standard only allows using dynamic/1 as a directive .

My understanding is that this implies that you can use dynamic/1 as a goal in a predicate body in SWI-Prolog, in contrast to what the ISO standard allows (and if you try it out you will see that you can, indeed, use dynamic/1 as a goal, not only as a directive).

I hope I am not misleading you on this.

1 Like

This also holds for assertz/1 and asserta/1. There reason is very simple. Only dynamic or unknown predicates can be used with database predicates assertz/1, asserta/1 and retract/1. This is the ISO core standard separation of known predicates into dynamic and static.

But then there are some differences among Prolog systems. According to ISO core standard clause/2 is also only allowed for unknown and dynamic predicates, but SWI-Prolog allows it for static predicates as well. Which can be quite useful sometimes.

Similarly there are differences in retract/1 and retractall/1 if the predicate is unknown. For example that SWI-Prolog creates a new dynamic entry during retractall/1, is not required by the standard. The usual bootstrapping(*) would be:

retractall(Head) :-
   retract((Head :- _)),
   fail.
retractall(_).

And according to ISO core standard retract/1 can fail silently if the predicate is unknown. This is seen here, where SWI-Prolog is compliant:

Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.22)

?- retract(foo(X)).
false.
?- listing(foo/1).
ERROR: Unknown procedure: foo/1 (DWIM could not correct goal)

(*) DRAFT TECHNICAL CORRIGENDUM 2
https://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#retractall

2 Likes

Got it. Thank you for the responses.

I have added a comment to:

https://eu.swi-prolog.org/pldoc/doc_for?object=(dynamic)/1

Breadcrumbs for the next guy!

Prolog is like The House of Leaves: Bigger Inside!

2 Likes