EN → DE A-AA+ Sitemap Search

# 6    Built-in Predicates

## 6.1    Higher-order Predicates

``````abolish( F, A) :- functor( Term, F, A), retract_all( Term).

retract_all( X) :- retract( X), fail.
retract_all( X) :- retract( X :- _), fail.
retract_all( _).

/* Testing */
assert_test :-
assert(test(1)),
assert(test(2)),
assert(test(3) :- test(a, b)),
assert(test(a, b)).

/* Test
?- assert_test.
?- test(X). => X = 1; X = 2; X = 3.
?- abolish(test, 1).
?- test(X). => false
?- test(X, Y). => X = a, Y = b
*/

filter( P, [ X| Xs], [ X| Ys]) :-
F =.. [P, X], call( F), !,
filter( P, Xs, Ys).
filter( P, [ _| Xs], Ys) :- filter( P, Xs, Ys).
filter( _, [], []).

pos( X) :- X > 0.
neg( X) :- X < 0.

/*
?- filter( pos, [ 1, -1, 2, -2], Y)    => Y = [ 1, 2].
?- filter( neg, [ 1, -1, 2, -2], Y)    => Y = [ -1, -2].
*/
``````

Back to example 6.1

## 6.2    Memoization

``````:- dynamic fibo/2.  /* a directive for SWI Prolog */

fibo( 0, 0).
fibo( 1, 1).
fibo( N, F) :-
N > 1, N1 is N - 1, N2 is N - 2,
fibo( N1, F1), fibo( N2, F2), F is F1 + F2,
asserta( fibo( N, F) :- !).

/* Iterative solution */
fibo_iter(Counter, F2, F1, Result) :-
Counter > 0,
Sum is F2 + F1,
F2_new = F1,
F1_new = Sum,
Counter1 is Counter - 1,
fibo_iter(Counter1, F2_new, F1_new, Result).
fibo_iter(0, F2, F1, Result) :-
Result = F1.

fibo_iter(0, 0).
fibo_iter(1, 1).
fibo_iter(N, F) :-
N > 1,
Counter is N - 1,
fibo_iter(Counter, 0, 1, F).

/* A more elegant formulation :
fibo_iter(Counter, F2, F1, Result) :-
Counter > 0,
Sum is F2 + F1,
Counter1 is Counter - 1,
fibo_iter(Counter1, F1, Sum, Result).
fibo_iter(0, _, Result, Result).
*/

``````

Back to example 6.2

## 6.3    User Interaction

``````/* Database */
:- dynamic dist/3.  /* a directive for SWI Prolog */
/* End Database */

/* Main Goal - type distances into the Prolog console */
distances :-
nl, write( 'Input: d( City1, City2).'),
nl, write( 'Quit: exit.'),
repeat,
nl, write( 'Input: '),
process_input( Input), !.

d( X, Y, D) :- dist( X, Y, D).
d( X, Y, D) :- dist( Y, X, D).

process_input( exit) :- !.
process_input( d( S1, S2)) :- distance( S1, S2, _), fail.

output( S1, S2, D) :-
nl, write( 'The distance between '), write( S1), write( ' and '), write( S2),
write( ' is '), write( D), write( ' km ').

distance( S1, S2, D) :- d( S1, S2, D), output( S1, S2, D), !.
distance( S1, S2, D) :- ask_user( S1, S2, D), !.

nl, write( 'I do not know. Please tell me:'),

process_answer( S1, S2, D, DR) :-
number( DR), !, D = DR, assert( dist( S1, S2, D)),
nl, write( 'Thank you. I confirm:'), output( S1, S2, D).
process_answer( S1, S2, D, _) :-
nl, write( '*** Invalid Input ***'), ask_user( S1, S2, D).

``````

Back to example 6.3

## 6.4    Counter

``````init( C, V) :- retractall( counter( C, _)),
assert( counter( C, V)), !.
get( C, V)  :- counter( C, V).
inc( C)     :- retract( counter( C, N)), N1 is N + 1,
assert( counter( C, N1)), !.
dec( C)     :- retract( counter( C, N)), N1 is N - 1,
assert( counter( C, N1)), !.
del( C)     :- retract( counter( C, _)).
``````

Back to example 6.4

## 6.5    Transformation of Facts into List Arguments

``````/* bagof and setof are predefined in SWI Prolog,
so we call them bag_of and set_of */

bag_of( X, P, _) :-
asserta( found( mark)),
call( P),
asserta( found(X)),
fail.
bag_of( _, _, B) :-
collect( [], B).

collect( B, BB) :-
retract( found( X)),
( X == mark -> BB = B
;  collect( [ X| B], BB)
), !.

/* The following set_of sorts the element of the list S */

set_of( X, P, S) :-
bag_of( X, P, L),
sort1( L, S).

sort1( [], []).
sort1( [ X1| Xs], Y) :-
sort1( Xs, Ys),
insert1( X1, Ys, Y).

insert1( X, [], [ X]).
insert1( X, [ Y1| Ys], [ X, Y1| Ys]) :- X < Y1.
insert1( X, [ Y1| Ys], [ Y1| Zs])    :- X > Y1, insert1( X, Ys, Zs).
insert1( X, [ X| Ys], [ X| Ys]).

/* Test data */
a(4).
a(1).
a(5).
a(3).
a(4).
a(1).

/* Test queries:
?- bag_of( X, a(X), B).         => B = [4, 1, 5, 3, 4, 1]
?- bag_of( b(c,X), a(X), B).    => B = [[b(c, 4), b(c, 1), b(c, 5), b(c, 3), b(c, 4), b(c, 1)]
?- bag_of( X, (a(X), X>2), B).  => B = [4, 5, 3, 4]

?- set_of( X, a(X), S).         => S = [1, 3, 4, 5]
?- set_of( b(c,X), a(X), S).    => Exception: S contains non-numerical elements
?- set_of( X, (a(X), X>2), S).  => S = [[3, 4, 5]
*/

``````

Back to example 6.5