
Expressions structurées 125
Le prédicat arg donne l’argument de rang spécifié au sein d’un terme, ainsi :
functor(comp(f, g), F, A). → F = comp A = 2
arg(2, fonc(f, g), A). → A = g
functor(+(X, 7), F, A). → X = _922 F = + A = 2
Ici, X est une variable, le foncteur F est le symbole + et le nombre
d’arguments A est 2.
Et pour bien comprendre qu’une liste est une construction à deux
arguments :
functor([a, b, c], F, A). → F = . A = 2
arg(2, [a, b, c], A). → A = [b, c]
arg(2, [a, b, c], A), arg(2, A, X). → A = [b, c] X = [c]
X =.. réalise l’inverse :
X =.. [+, a, b]. → X = a + b
X =.. [f, a, b, c]. → X = f(a, b, c)
et f(a, b, c) =.. X. → X = [f, a, b, c]
Attention une constante est elle-même un terme d’arité zéro :
a =.. [X | Q]. → X = a Q = []
1 Substitution
Un terme T1 est substitué par un autre terme T2 au sein d’un troisième devant
donner le résultat R.
La première clause indique bien le terme à remplacer de façon impérative,
c’est-à-dire que la coupure empêche de faire autre chose les deux dernières
clauses disent ce qu’il faut faire récursivement pour explorer un terme en
passant par la liste associée, et la seconde clause comporte la condition atom
qui signifie qu’on ne doit rien faire en cas d’un terme atomique différent de ce
que l’on a spécifié à substituer, et ceci pour la raison déjà dite qu’une constante
est elle-même un terme d’arité zéro.
sub(T1, T2, T1, T2) :- !.
sub(_, _, T, T) :- atom(T), !.
sub(T1, T2, [T | Q], [TS | QS]) :- !, sub(T1, T2, T, TS), sub(T1, T2, Q, QS).
sub(T1, T2, T, R) :- T =.. [F | A], sub(T1, T2, A, RA), R =.. [F | RA].
sub(cos(x), exp(y), 3*cos(2*x) + 5*cos(x) − 2*log(cos(x)), R).
→ R = 3*cos(2*x) + 5*exp(y) − 2*log(exp(y))