Entity:

**the_head_of**
**set_at**
**retract_at**
**modify_at**

Entity: **predicates**

Usage:
**R is on_the_last_step(Flag)**
**the_head_of(Number, Head)**
**set_at(Number, Fact)**
**retract_at(Number)**
**modify_at(Number, Position, New_Value)**

**Direct Database Manipulation**

This predicates are very useful for AI applications.

When you make unification with a fact in your database you don't know which exactly is this fact. You can check the variables of the goal to understand something about this fact but you cannot understand everything (especially if the fact is a more general case than the goal). The following function will help you to understand the consecutive number of this fact in the database.

**Number is on_the_last_step(Flag)**

You have to call this function immediately after the unification in
which you are interested. **Number** will be the consecutive number
of the fact (or clause) in the program used in the last unification.

The **Flag** can have one of the following values:

**a** - the function will succeed in **All** cases.

**e** - the function will succeed only if on the last step the unification
was made between **Exactly** equal goal and fact (equal up to
renaming of variables). For example exactly equal are the goal **p(X,
f(Y))** and the fact **p(A, f(B))** or **p(_, f(_))**.

**s** - the function will succeed only if on the last step the unification
was made between **Similar** goal and fact (equal up to substitution
of some variables with other variables or special
types). For example similar but not exactly equal are the goal **p(X,
f(Y))** and the fact **p(A, f(A))** or **p(1, f("String"))**
but it is not similar to the facts **p(X, f(a))** and **p(X, Y)**.

If you know the consecutive number of one fact (for example from **on_the_last_step**
function) and if you want to receive this fact then use:

**the_head_of(Number, Head)**

where **Number** is the consecutive number in the database and **Head**
will return the fact which is on that number. If it is not a fact but a
clause then the head of this clause will be returned.

You can modify a fact in your database by knowing its consecutive number. For this you can use the following predicates:

**set_at(Number, Fact)**
**retract_at(Number)**
**modify_at(Number, Position, New_Value)**

**retract_at** will retract the fact (or clause) which has consecutive
number **Number**.
**set_at** will do more. It will retract the fact on this position
and will assert in the same place the fact **Fact**.

With **modify_at** you can change one fact without retracting it.
You have to specify the **Number** of the fact, the **Position**
of the variable which you want to change and the new value with which to
modify.

The old and the new values of the modified variable have to be a special type. This mean that you cannot change a free variable with number and vice versa but you can change integer with a string.

Position of the modified variable is the zero based index of the position
of this variable in the fact. For example, in the fact **p(a, X, f(X,Z)
, b, 7, Y, Z) X** has position zero, **Z** has position one and **Y**
has position three. The position two is occupied by a variable which value
is **7** and this is the only variable in this fact which may to be
modified because other are free.

The predicate **modify_at** is very efficient and is very convenient
for work with large databases.

The following example prints all facts which are similar to **p(X,
f(Y))** in the database:

*?-*
* p(X, f(Y)),*
* R is on_the_last_step(s),
% try with "a" and with "e"*
* write(R), nl,*
* the_head_of(R, X),*
* writeq(X), nl,*
* fail.*

*p(A, f(A)).*
*p(A, f(B)).*
*p(X, f(a)).*

The following example increments the value of the first (position 0)
argument of all predicates similar to **p(N, 5)** (and unifyable with
it). Look at **System List** (in menu **Tools**) to see the result
of the execution of this example.

*?-*
* p(N, 5),*
* R is on_the_last_step(s),
% try with "a" and with "e"*
* write(R), nl,*
* modify_at(R, 0, N+1),*
* fail.*

*p(1, 5). % OK*
*p(2, 5). % OK*
*p(A, 5). % A is not a special
type*
*p(X, X). % X is not a
special type*
*p(1, 6). % this is not
unifyable with p(N, 5)*

Look at the example:
**AI 2.spj** (in folder AI)