Dynamic clause management
Author: Daniel Diaz
Keywords: GNU Prolog, manual, Prolog, compiler, constraints, finite domains

### 8.7 Dynamic clause management

- Introduction
- asserta/1, assertz/1
- retract/1
- retractall/1
- clause/2
- abolish/1

#### 8.7.1 Introduction

Static and dynamic procedures: a procedure is either dynamic or static. All built-in predicates are static. A user-defined procedure is static by default unless a dynamic/1 directive precedes its definition (section 7.1.2). Adding a clause to a non-existent procedure creates a dynamic procedure. The clauses of a dynamic procedure can be altered (e.g. using asserta/1), the clauses of a static procedure cannot be altered.

Private and public procedures: each procedure is either public or private. A dynamic procedure is always public. Each built-in predicate is private, and a static user-defined procedure is private by default unless a public/1 directive precedes its definition (section 7.1.3). If a dynamic declaration exists it is unnecessary to add a public declaration since a dynamic procedure is also public. A clause of a public procedure can be inspected (e.g. using clause/2), a clause of a private procedure cannot be inspected.

A logical database update view: any change in the database that occurs as the result of executing a goal (e.g. when a sub-goal is a call of assertz/1 or retract/1) only affects subsequent activations. The change does not affect any activation that is currently being executed. Thus the database is frozen during the execution of a goal, and the list of clauses defining a predication is fixed at the moment of its execution.

#### 8.7.2 asserta/1, assertz/1

Templates

  asserta(+clause)
  assertz(+clause)

Description

asserta(Clause) first converts the term Clause to a clause and then adds it to the current internal database. The predicate concerned must be dynamic (section 8.7.1) or undefined and the clause is inserted before the first clause of the predicate. If the predicated is undefined it is created as a dynamic procedure.

assertz(Clause) acts like asserta/1 except that the clause is added at the end of all existing clauses of the concerned predicate.

Converting a term Clause to a clause Clause1:

- extract the head and the body of Clause: either Clause = (Head :- Body) or Clause = Head and Body = true.
- Head must be a callable term (or else the conversion fails).
- convert Body to a body clause (i.e. a goal) Body1.
- the converted clause Clause1 = (Head :- Body1).

Converting a term T to a goal:

- if T is a variable it is replaced by the term call(T).
- if T is a control construct (’,’)/2, (;)/2 or (->)/2 each argument of the control construct is recursively converted to a goal.
- if T is a callable term it remains unchanged.
- otherwise the conversion fails (T is neither a variable nor a callable term).

Errors

Head is a variable |  | instantiation_error
Head is neither a variable nor a callable term |  | type_error(callable, Head)
Body cannot be converted to a goal |  | type_error(callable, Body)
The predicate indicator Pred of Head is that of a static procedure |  | permission_error(modify, static_procedure, Pred)

Portability

ISO predicates.

#### 8.7.3 retract/1

Templates

  retract(+clause)

Description

retract(Clause) erases the first clause of the database that unifies with Clause. The concerned predicate must be a dynamic procedure (section 8.7.1). Removing all clauses of a procedure does not erase the procedure definition. To achieve this use abolish/1 (section 8.7.6). retract/1 is re-executable on backtracking.

Errors

Head is a variable |  | instantiation_error
Head is neither a variable nor a callable term |  | type_error(callable, Head)
The predicate indicator Pred of Head is that of a static procedure |  | permission_error(modify, static_procedure, Pred)

Portability

ISO predicate. In the ISO reference, the operation associated with the permission_error is access while it is modify in GNU Prolog. This seems to be an error of the ISO reference since for asserta/1 (which is similar in spirit to retract/1) the operation is also modify.

#### 8.7.4 retractall/1

Templates

  retractall(+head)

Description

retractall(Head) erases all clauses whose head unifies with Head. The concerned predicate must be a dynamic procedure (section 8.7.1). The procedure definition is not removed so that it is found by current_predicate/1 (section 8.8.1). abolish/1 should be used to remove the procedure (section 8.7.6).

Errors

Head is a variable |  | instantiation_error
Head is not a callable term |  | type_error(callable, Head)
The predicate indicator Pred of Head is that of a static procedure |  | permission_error(modify, static_procedure, Pred)

Portability

ISO predicate.

#### 8.7.5 clause/2

Templates

  clause(+head, ?callable_term)

Description

clause(Head, Body) succeeds if there exists a clause in the database that unifies with Head :- Body. The predicate in question must be a public procedure (section 8.7.1). Clauses are delivered from the first to the last. This predicate is re-executable on backtracking.

Errors

Head is a variable |  | instantiation_error
Head is neither a variable nor a callable term |  | type_error(callable, Head)
The predicate indicator Pred of Head is that of a private procedure |  | permission_error(access, private_procedure, Pred)
Body is neither a variable nor a callable term |  | type_error(callable, Body)

Portability

ISO predicate.

#### 8.7.6 abolish/1

Templates

  abolish(+predicate_indicator)

Description

abolish(Pred) removes from the database the procedure whose predicate indicator is Pred. The concerned predicate must be a dynamic procedure (section 8.7.1).

Errors

Pred is a variable |  | instantiation_error
Pred is a term Name/Arity and either Name or Arity is a variable |  | instantiation_error
Pred is neither a variable nor a predicate indicator |  | type_error(predicate_indicator, Pred)
Pred is a term Name/Arity and Arity is neither a variable nor an integer |  | type_error(integer, Arity)
Pred is a term Name/Arity and Name is neither a variable nor an atom |  | type_error(atom, Name)
Pred is a term Name/Arity and Arity is an integer < 0 |  | domain_error(not_less_than_zero, Arity)
Pred is a term Name/Arity and Arity is an integer > max_arity flag (section 8.22.1) |  | representation_error(max_arity)
The predicate indicator Pred is that of a static procedure |  | permission_error(modify, static_procedure, Pred)

Portability

ISO predicate.

Copyright (C) 1999-2021 Daniel Diaz Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved. More about the copyright