on_the_last_step
Entity: function

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)