4. Opérations prédéfinies sur les données. PrologIA HERITAGE II+
A!ociation
Prolog
HERITAGE
4. Opérations prédéfinies sur les données
4.1. Les tests de type
4.2. Les opérations arithmétiques
4.3. Affectation
4.4. Opérations sur les chaînes
4.5. Composition et décomposition d'objets
4.6. Comparaison de termes quelconques
4.1. Les tests de type
Ces règles permettent de connaître le type d'un objet. Si l'argument est une variable libre, ces règles n'ont pas de sens et échouent.
ident(t)
Vérifie que t est un identificateur.
integer(t)
Vérifie que t est un entier.
real(t)
Vérifie que t est un réel.
double(t)
Identique à real(t).
dot(t)
Vérifie que t est de la forme t1.t2 ou [ t1 | t2 ].
string(t)
Vérifie que t est une chaîne.
tuple(t)
Vérifie que t est un terme de la forme f(t1 … tn) ou <t1 … tn>.
Les primitives suivantes concernent l'«état» des variables et ont donc un esprit voisin de celui des tests de type :
bound(x)
bound(x) s'efface si x est lié. Une variable est considérée comme liée si elle a
été unifiée contre :
©PrologIA
R 4 - 2
Manuel de Référence
- une constante (entier, réel, identificateur, chaîne),
- un terme de la forme t1.t2,
- un terme de la forme <t1, t2, … , tn> ou ff(t1, t2, … , tn).
free(x)
S'efface uniquement si x n'est pas lié.
var_time(x,n)
Date de création d'une variable.
x doit être une variable libre. Cette règle prédéfinie unifie n avec la «date de création» de la variable x : il s'agit d'un nombre entier qui identifie de manière unique la variable; deux variables ont la même date si et seulement si elles sont liées entre elles (c'est ce même nombre qui est utilisé par le compilateur pour l'impression des variables libres -- voir l'exemple ci-dessous).
Exemple:
>eq(x,y) var_time(x,_tx) var_time(y,_ty) var_time(z,_tz)
out(x.y.z) line;
v35.v35.v172
{y=x, _tx=35, _ty=35, _tz=172}
>
La date de création d'une variable correspond à une notion du «temps» qui est sensiblement la même que celle de l'horloge Prolog : le temps avance lors de l'effacement des buts et recule avec le backtracking. Dans l'exemple suivant, la variable x est créée trois fois; on constate qu'elle possède bien la même date de création:
>enum(i,3) var_time(x,t);
{i=1,t=35}
{i=2,t=35}
{i=3,t=35}
>
Attention, la valeur de la date de création des variables n'est pas invariante lors des tassages des piles par le garbage collector.
A!ociation
Prolog
HERITAGE
4.2. Les opérations arithmétiques
L'évaluation d'une expression est faite au moyen de la règle prédéfinie val. Le résultat d'une évaluation est soit un entier, soit un réel, soit un identificateur, soit une chaîne. Les booléens sont représentés par les entiers 0 et 1.
©PrologIA
A!ociation
Prolog
HERITAGE
Opérations prédéfinies sur les données
R 4 - 3
val(t1, t2) tval(t1, t2)
Evaluent l'expression t1 et unifient le résultat avec t2. L'expression à évaluer est construite récursivement à partir des constantes, des identificateurs, des
éléments de tableau et des fonctions évaluables. Les optimisations (si elles n'ont pas été désactivées au lancement de Prolog) du code généré pour l'appel au prédicat val ne permettent pas, pour la décompilation ou la mise au point, de restituer le terme d'origine mais un terme équivalent. De plus elles suspendent momentanément le mécanisme de gestion automatique des espaces et des piles. Le prédicat tval lui, n'est pas optimisé. On pourra le préférer à val dans les cas de programmes consommateurs d'espace où val manipule fréquemment des termes complexes. On évitera ainsi d'avoir à faire une gestion "manuelle" de la mémoire.
Exemples:
>val(add(mul(2, add(3, 4)), 1000), x);
{x=1014}
>val(add(mul(2e0, add(3, 4e0)), 1000), x);
{x=1.014000e+03}
>val(2 * (3 + 4) + 1000, x);
{x=1014}
Les fonctions arithmétiques peuvent avoir des arguments de types différents, dans ce cas il y a une conversion automatique des types en type le plus général (les types sont, par ordre décroissant: réel, entier). Quand une fonction
à évaluer a un nombre incorrect d'arguments ou quand certains de ses arguments sont du mauvais type, val produit une erreur. Cette erreur est récupérable par la règle prédéfinie block.
• La valeur d'un nombre ou d'une chaîne est égale à ce nombre ou à cette chaîne.
• La valeur d'un tableau (externe ou interne) indicé est égale à la valeur de l'élément correspondant de ce tableau. Exemple:
>def_array(tab,100) assign(tab[50],3);
{}
>val(tab[50],_x);
{_x=3}
• La valeur d'un identificateur i est définie comme suit :
(1) si un terme t a été affecté à i (au moyen de la règle assign : voir le paragraphe suivant) alors la valeur de i est t.
(2) si i n'a pas fait l'objet d'une affectation préalable, alors la valeur de i est i lui-même.
Exemple :
>assign(un, 1);
{}
>val(un, x) val(deux, y);
{x=1,y=deux}
©PrologIA
R 4 - 4
Manuel de Référence
Certaines fonctions évaluables peuvent aussi être exprimées à l'aide d'opérateurs.
Les fonctions évaluables sont :
add(t1, t2) ou t1 + t2 valeur(add(t1, t2)) = valeur(t1) + valeur(t2).
Les valeurs de t1 et t2 doivent être de type entier ou réel.
sub(t1, t2) ou t1 - t2 valeur(sub(t1, t2)) = valeur(t1) - valeur(t2).
Les valeurs de t1 et t2 doivent être de type entier ou réel.
mul(t1, t2) ou t1 * t2 valeur(mul(t1, t2)) = valeur(t1) * valeur(t2).
Les valeurs de t1 et t2 doivent être de type entier ou réel.
div(t1, t2) ou t1 / t2 valeur(div(t1, t2)) = valeur(t1) / valeur(t2).
Les valeurs de t1 et t2 doivent être de type entier ou réel.
mod(t1, t2) ou t1 mod t2 valeur(mod(t1, t2)) = valeur(t1) modulo valeur(t2).
mod (modulo) se différencie de rem (remainder) dans le cas où les opérandes
t1 et t2 sont de signes contraires. En effet dans ce cas, le second opérande (t2) est ajouté au reste de la division entière de t1 par t2 (remainder).
Les valeurs de t1 et t2 doivent être de type entier.
rem(t1, t2) ou t1 rem t2 valeur(rem(t1, t2)) = reste de la division entière de t1 par t2.
Les valeurs de t1 et t2 doivent être de type entier.
eql(t1, t2) ou t1 =:= t2 ou =:=(t1, t2) valeur(eql(t1, t2)) = si valeur(t1) = valeur(t2) alors 1 sinon 0.
Si t1 et t2 sont de type arithmétique, la conversion automatique des types est appliquée avant l'évaluation.
'=\='(t1, t2) ou t1 =\= t2 valeur(=\=(t1, t2)) = si valeur(t1) ! valeur(t2) alors 1 sinon 0.
Si t1 et t2 sont de type arithmétique, la conversion automatique des types est appliquée avant l'évaluation.
inf(t1, t2) ou t1 '<' t2 valeur(inf(t1, t2)) = si valeur(t1) < valeur (t2) alors 1 sinon 0.
Pour les entiers et les réels, on prend la relation "<" entre les nombres. Pour les chaînes, on prend l'ordre alphabétique et pour les identificateurs, on prend l'ordre alphabétique sur les chaînes associées.
A!ociation
Prolog
HERITAGE
©PrologIA
A!ociation
Prolog
HERITAGE
Opérations prédéfinies sur les données
R 4 - 5
infe(t1, t2) ou t1 '=<' t2 valeur(infe(t1, t2)) = si valeur(t1) " valeur (t2) alors 1 sinon 0. Cf. inf.
sup(t1, t2) ou t1 '>' t2 valeur(sup(t1, t2)) = si valeur(t1) > valeur (t2) alors 1 sinon 0. Cf. inf.
supe(t1, t2) ou t1 '>=' t2 valeur(supe(t1, t2)) = si valeur(t1) # valeur (t2) alors 1 sinon 0. Cf. inf.
if(t, t1, t2) valeur(if(t, t1, t2)) = si (valeur(t)!0) alors valeur(t1) sinon valeur(t2).
sign(t)
valeur (sign(t))= si valeur(t) = 0 alors 0, si valeur(t) < 0 alors -1, sinon 1.
La valeur de t doit être de type entier ou réel.
ceiling(t)
valeur (ceiling(t))= - (partie entière(-valeur(t)))
La valeur de t doit être de type entier ou réel. Le résultat est de type entier.
floor(t)
valeur (floor(t)) = partie entière(valeur(t)) .
La valeur de t doit être de type entier ou réel. Le résultat est de type entier.
round(t)
valeur(round(t))= partie entière(valeur(t)+0.5).
La valeur de t doit être de type entier ou réel. Le résultat est de type entier.
trunc(t)
valeur(trunc(t)) = conversion en entier de la valeur de t.
La valeur de t doit être de type entier ou réel.
float(t)
valeur(float(t)) = conversion en réel de la valeur de t.
La valeur de t doit être de type entier ou réel.
double(t)
valeur(double(t)) = conversion en réel de la valeur de t.
La valeur de t doit être de type entier ou réel.
abs(t)
valeur(abs(t)) = valeur absolue de la valeur de t.
La valeur de t doit être de type entier ou réel.
Les fonctions suivantes doivent être appliquées à des arguments de type entier. Elles donnent un résultat de type entier.
©PrologIA
R 4 - 6
Manuel de Référence
'/\'(t1,t2)
valeur('/\'(t1,t2)) = 'et' bit à bit entre t1 et t2.
'\/'(t1,t2)
valeur('\/'(t1,t2)) = 'ou' bit à bit entre t1 et t2.
'<<'(t1,t2)
valeur('<<'(t1,t2)) = t1 décalé de t2 bits vers la gauche.
'>>'(t1,t2)
valeur('>>'(t1,t2)) = t1 décalé de t2 bits vers la droite.
'~'(t)
valeur('~'(t)) = complément bit à bit de t.
Les fonctions suivantes doivent être appliquées à des entiers ou des réels et donnent un résultat de type réel. Les fonctions trigonométriques travaillent avec des angles exprimés en radians.
atan(t)
valeur (atan(t)) = arc tangente(valeur(t)).
cos(t)
valeur (cos(t)) = cosinus(valeur(t)).
exp(t)
valeur (exp(t)) = exponentielle(valeur(t)).
ln(t)
valeur(ln(t)) = logarithme népérien(valeur(t)).
rad(t)
valeur(rad(t)) = conversion en radian(valeur(t)).
sin(t)
valeur(sin(t)) = sinus(valeur(t)).
sqrt(t)
valeur(sqrt(t)) = racine carrée(valeur(t)).
tan(t)
valeur(tan(t)) = tangente(valeur(t)).
t1 ** t2 valeur(t1 ** t2) = valeur(t1) à la puissance valeur(t2).
A!ociation
Prolog
HERITAGE
©PrologIA
A!ociation
Prolog
HERITAGE
Opérations prédéfinies sur les données
R 4 - 7
4.3. Affectation
assign(i, t) tassign(i, t) cassign(i, t)
Affectent le terme t à l'identificateur i, t peut être un terme Prolog quelconque.
Tout se passe comme si i devenait le nom d'une variable «globale»
(ultérieurement accessible pendant l'effacement de n'importe quel but) et
«statique» (résistante au backtracking) possédant t pour valeur. Il s'agit donc bien de l'affectation classique, comme elle se pratique dans F
ORTRAN
, Pascal, etc…. Les optimisations (si elles n'ont pas été désactivées au lancement de
Prolog) du code généré pour l'appel au prédicat assign suspendent momentanément le mécanisme de gestion automatique des espaces et des piles. Le prédicat tassign lui, n'est pas optimisé. On pourra le préférer à
assign dans les cas de programmes consommateurs d'espace où assign manipule fréquemment des termes complexes. On évitera ainsi d'avoir à faire une gestion "manuelle" de la mémoire. Le prédicat cassign est similaire au prédicat tassign mais permet de conserver les contraintes (dif, freeze) et les attributs (variables attribuées) associés aux variables du terme t.
Exemple :
>assign(nom_fichier, "monfichier.txt");
{}
>val(nom_fichier,x)
{x="monfichier.txt"}
>
En Prolog, ces variables statiques peuvent être vues comme une manière particulièrement efficace de réaliser des assertions (ou règles sans queue). Du point de vue de l'utilisateur, on peut considérer que l'emploi de assign et val fait ci-dessus est conceptuellement équivalent à:
>retract(nom_fichier(x), nil);
>assert(nom_fichier("monfichier.txt"), nil);
{}
>nom_fichier(x);
{x="monfichier.txt"}
>
Exemple : possibilité d'affecter un terme quelconque, et non uniquement des constantes.
>assign(myterm, jean.<34,"rue blanche">.A_utres_infos);
{}
>val(myterm,x) val(myterm,y);
{x=jean.<34,"rue blanche">.v64,y=jean.<34,"rue
blanche">.v65}
>
assign(tab(i), t) ou assign(tab[i], t)
tassign(tab(i), t) ou tassign(tab[i], t)
Affectent le terme t à l'élément de rang i du tableau tab. Ce tableau doit avoir
été défini au préalable avec def_array.
©PrologIA
R 4 - 8
Manuel de Référence
Pour l'accès à des éléments de tableaux (dans val) les notations tab(i) et tab[i] sont équivalentes; cependant, elles ne sont pas représentées par les mêmes termes Prolog, et dans le cas de l'utilisation de tab[i] le compilateur optimise l'accès au tableau. Pratiquement, on réservera la notation tab[i] pour la désignation d'éléments de tableau uniquement. Nous ferons également la même remarque que précédemment concernant les optimisations : assign est optimisé, tassign ne l'est pas.
backtrack_term
Tableau prédéfini du module sys, de longueur 100 (indices possibles entre 1 et 100) qui peut être manipulé à l'aide des prédicats prédéfinis val ou tval et
assign ou tassign. Les valeurs qui lui sont assignées sont perdues au backtracking. Chaque élément du tableau est initialisé à 0. Exemple:
> insert;
test(i) -> assign(backtrack_term[1],111) val(backtrack_term[1],i); test(i) -> val(backtrack_term[1],i);
;
{}
> test(i);
{i=111}
{i=0}
def_array(i, n)
Définit dynamiquement un tableau de termes Prolog de nom i et de taille n. Ce tableau se comportera comme une variable «globale» (ultérieurement accessible pendant l'effacement de n'importe quel but) et «statique» (résistante au backtracking). Chaque élément du tableau est initialisé avec l'entier 0. Les valeurs légales de l'indice sont incluses dans 1..n.
Si un tableau de même nom existe déjà :
- s'il s'agit d'un tableau de même taille, il ne se passe rien
- si les tailles diffèrent, il se produit une erreur
L'accès et l'affectation sont analogues à ceux des tableaux des autres langages de programmation : voir ci-dessus val pour l'accès et assign pour l'affectation.
Le tableau est désalloué lorsqu'on tue le module auquel il appartient (c.à.d. les règles ayant le même préfixe) ou bien lorsqu'on exécute le prédicat kill_array.
"gestion d'une pile" inc(i) -> val(i + 1, x) assign(i, x); dec(i) -> val(i - 1, x) assign(i, x); initialise -> assign(pointeur,0) def_array(pile,100); empile(v) ->
inc(pointeur)
val(inf(pointeur,100),1)
!
val(pointeur,p)
assign(pile[p], v); empile(v) -> outml("débordement de la pile") fail;
A!ociation
Prolog
HERITAGE
©PrologIA
A!ociation
Prolog
HERITAGE
Opérations prédéfinies sur les données
R 4 - 9
depile(v) ->
val(eql(pointeur,0),0)
!
val(pile[pointeur],v)
dec(pointeur); depile(v) -> outm("pile vide") line fail;;
>initialise;
{}
>empile(12345);
{}
>empile(23456);
{}
>depile(x) depile(y);
{x=23456, y=12345}
>depile(x);
redef_array(i, n)
Analogue à def_array mais, si le tableau de nom i existe déjà, redéfinit sa taille: n, conserve les affectations existantes pour les indices valides, et initialise s'il y a lieu les nouveaux éléments.
is_array(i,t)
Vérifie que l'identificateur i désigne bien un tableau et unifie t avec sa taille.
kill_array(i)
Détruit le tableau de nom i. Si le tableau n'est pas défini, le prédicat s'efface en imprimant éventuellement 1 un warning.
4.4. Opérations sur les chaînes
char_code(c, n)
Fait correspondre au caractère c son code interne n et vice-versa. Ce code peut
être un code ISO 2 ou le code de la machine hôte. Si c est un identificateur dont la représentation (hormis les quotes) est limitée à un caractère, le code correspondant est unifié avec n.
Exemple :
>char_code("A",n) char_code('A',n);
{n=65}
>char_code(c,65);
{c="A"}
1
Cela dépend du niveau de warning choisi par une option au lancement de Prolog.
2Il s'agit du code ISO 8859-1 (voir la table complète en annexe F). Ce jeu est le jeu ASCII américain étendu sur 8 bits avec des caractères accentués.
©PrologIA
R 4 - 10
Manuel de Référence
conc_string(s1, s2, s3)
Enumère tous les triplets s1, s2, s3 de chaînes telles que s3 est la concaténation de s1 et s2. s1, s2, s3 doivent être suffisamment connus pour produire des ensembles finis de triplets, c'est à dire soit le troisième argument connu, soit deux des trois chaînes connues.
Exemple :
>conc_string("ab", "cd", s);
{s="abcd"}
>conc_string(s1, s2, "abcd");
{s1="",s2="abcd"}
{s1="a",s2="bcd"}
{s1="ab",s2="cd"}
{s1="abc",s2="d"}
{s1="abcd",s2=""}
substring(s1, i, j, s2)
Extrait de la chaîne s1 une sous-chaîne commençant à la position i, de longueur j et essaie de l'unifier avec s2.
Exemple :
>substring("1234567890", 3, 4, x);
{x="3456"}
find_pattern(s1, s2, n)
Unifie n avec la position du début de la chaîne s2 dans la chaîne s1. Si s2 n'est pas trouvé, alors l'effacement de find_pattern échoue.
Exemple :
>find_pattern("1234567890", "3456", p);
{p=3}
>find_pattern("1234567890", "abcd", p);
>
Note:
Cette primitive est définie dans le module externe prouser.c, la modification inconsidérée du source correspondant peut être responsable de son malfonctionnement. Dans le source livré, la longueur des chaînes est limitée à 256 caractères.
A!ociation
Prolog
HERITAGE
4.5. Composition et décomposition d'objets
arg2(n, t1, t2)
Unifie t2 avec la longueur ou l'élément de rang n d'un n-uplet, d'une liste ou d'une chaîne.
(1) Si t1 est une chaîne alors si
n=0, t2 = longueur(t1)
n!0, t2 = nième caractère de la chaîne t1.
©PrologIA
A!ociation
Prolog
HERITAGE
Opérations prédéfinies sur les données
R 4 - 11
(2) Si t1 est une liste alors si
n=0, t2 = nombre d'éléments de la liste
n!0, t2 = nième élément de la liste t1.
(3) Si t1 est un n-uplet alors si
n=0, t2 = nombre d'arguments du n-uplet
n!0, t2 = nième argument du n-uplet t1.
Exemples :
>arg2(0,"abcdef",x);
{x=6}
>arg2(3,"abcdef",x);
{x="c"}
>arg2(0,aa.bb.cc.dd.ee.ff.nil,x);
{x=6}
>arg2(3,aa.bb.cc.dd.ee.ff.nil,x);
{x=cc}
>arg2(0,<aa,bb,cc,dd,ee,ff>,x);
{x=6}
>arg2(3,<aa,bb,cc,dd,ee,ff>,x);
{x=cc}
arg(n, t1, t2)
La primitive correspondante de l'interpréteur Prolog II a été renommée arg2 dans le compilateur. arg/3 est une règle prédéfinie du mode Edinburgh.
conc_list_string(l, s)
Concatène les chaînes de la liste l pour créer la chaîne s.
Exemple :
>conc_list_string("How "."are "."you "."?".nil, x);
{x="How are you ?"}
copy_term(t1, t2)
Fait une copie du terme t1 en remplaçant chaque variable libre (contrainte ou pas) par une nouvelle variable sans contrainte et unifie cette copie avec t2.
C'est à dire que les deux termes sont représentés par le même arbre, aux noms de variables près. t1 est un terme prolog quelconque, voire infini.
Exemple :
>copy_term(one(2.x,y), t);
{t=one(2.v33,v31)}
copy_term_with_constraints(t1, t2)
Analogue au prédicat copy_term/2 mais copie les contraintes sur les variables.
©PrologIA
R 4 - 12
Manuel de Référence
enum(i, k1, k2)
enum(i, k2)
k1 et k2 doivent être des entiers connus. Si k1 > k2 alors on a un échec. Par définition, cette règle s'efface de k2-k1+1 manières : la première consiste à unifier i et k1; la deuxième consiste à unifier i et k1+1, etc…; la dernière consiste à unifier i et k2.
Exemple :
>enum(i,5,9);
{i=5}
{i=6}
{i=7}
{i=8}
{i=9}
La deuxième forme, enum(i,k), équivaut à enum(i,1,k).
gensymbol(i)
Crée un nouvel identificateur de la forme idn, où n est un entier, et l'unifie avec
i.
list_string(l, s)
Compose une chaîne s à partir d'une liste l de caractères.
Exemple :
>list_string("H"."e"."l"."l"."o".nil, x);
{x="Hello"}
list_tuple(l, t)
Compose un n-uplet t à partir de la liste d'arguments l.
Exemple :
>list_tuple(111.aaa.222."Hello".nil,x);
{x=<111,aaa,222,"Hello">}
member(x,l)
Unifie successivement x avec chaque élément de la liste l. Est décrit par les règles : member(x, x.l) ->; member(x, _.l) -> member(x, l);
setarg(n, t1, t2)
Remplace l'élément de rang n du terme t1 par le terme t2. t1 doit être une liste ou bien un n-uplet. Le terme initial est restauré sur un backtracking.
Exemple:
> reinsert;
newarg(55) ->; newarg(66) ->;;
{}
> eq(x, 1.2.3.nil) newarg(y) arg2(2,x,e1) setarg(2,x,y)
arg2(2,x,e2);
{x=1.55.3.nil, y=55, e1=2, e2=55}
{x=1.66.3.nil, y=66, e1=2, e2=66}
A!ociation
Prolog
HERITAGE
©PrologIA
A!ociation
Prolog
HERITAGE
Opérations prédéfinies sur les données
R 4 - 13
split(t, l)
Décompose une chaîne ou un n-uplet en la liste de ses composants. Au moment de l'effacement de split(t, l), t doit être connu; on a alors :
Si t est une chaîne, l est unifié avec la liste de ses caractères.
Si t est un n-uplet, l est unifié avec la liste des arguments de t.
Sinon échec.
Exemple :
>split("abcde", x);
{x="a"."b"."c"."d"."e".nil}
>split(plusgrand(Jean, Pierre.Marie), x));
{x=plusgrand.Jean.(Pierre.Marie).nil}
string_ident(s1, s2, i)
string_ident(s, i)
Etablit la correspondance entre un identificateur et sa représentation sous forme de chaîne. Si l'identificateur n'existe pas, il est créé. Dans la forme à trois arguments, fait correspondre aux chaînes s1 et s2 l'identificateur dont le préfixe est s1 et la représentation abrégée s2, et vice-versa. Dans la forme à deux arguments, utilise le contexte courant de lecture/écriture pour établir la relation entre l'identificateur i et sa représentation s. s peut être une représentation complète ou une représentation abrégée.
Exemple :
>string_ident(p, i, invites:Jean);
{p="invites",i="Jean"}
>string_ident("invites","Jean",x);
{x=invites:Jean}
Exemple dans le contexte standard :
>string_ident(s,sys:outm);
{s="outm"}
string_integer(s, n)
Fait correspondre la chaîne s à l'entier n et vice-versa.
>string_integer(s,123);
{s="123"}
>string_integer("-0123",n);
{n=-123}
string_real(s, r)
Fait correspondre la chaîne s au réel r et vice-versa.
>string_real(s,12.34e5) string_real(s,x);
{s="1.234000000000000e+06",x=1.234000000000000e+06}
>string_real(s,1d110) string_real(s,x);
{s="1.000000000000000e+110",x=1.000000000000000e+110}
string_double(s, d)
Identique à string_real(s,d).
©PrologIA
R 4 - 14
Manuel de Référence string_term(s, t, s',n) string_term(s, t, s') string_term(s, t)
Essaie de lire dans la chaîne de caractères s un terme Prolog qui sera unifié avec t. s' est la partie de la chaîne s qui n'a pas pu être utilisée. Si une variable apparaît dans s, une variable libre Prolog est créée.
Inversement (si s n'est pas connue) écrit, à la façon de out(t), le terme t dans une chaîne de taille maximale de n caractères (400<n < 32768) et l'unifie avec
s, s' n'est pas utilisée dans ce cas. t est un terme tout à fait quelconque, pouvant même contenir des variables et des structures complexes. Si l'écriture de t ne tient pas sur n caractères une erreur est générée. Si n n'est pas spécifié,
400 est choisi.
>string_term(s,myterm(x,1.2e0),s') string_term(s,x,s');
{s="myterm(v14,1.200000000000000e+00)",x=myterm(v15,1.2000
00000000000e+00), s'=""}
>string_term("1.2,3)",t,s') string_term(s,t,s');
{t=1.2,s'=",3)",s="1.2"}
term_vars(t, l)
Unifie l avec la liste des variables libres, éventuellement contraintes, de t. t est un terme prolog quelconque, voire infini.
Exemple :
>term_vars(one(2.x,y,y), t);
{t=x.y.nil}
A!ociation
Prolog
HERITAGE
4.6. Comparaison de termes quelconques
Il est possible de comparer formellement deux termes Prolog quelconques. Pour cela, l'ordre croissant suivant sur les termes a été défini:
- les variables
- les réels
- les entiers
- les identificateurs
- les chaînes de caractères
- les n-uplets de longueur < 2.
- les listes
- les n-uplets de longueur >= 2.
©PrologIA
A!ociation
Prolog
HERITAGE
Opérations prédéfinies sur les données
R 4 - 15
La comparaison de deux variables est fonction de leur date de création. La comparaison de deux entiers ou deux réels suit les règles habituelles. La comparaison de deux chaînes de caractères ou deux atomes suit l'ordre alphanumérique. La comparaison de deux listes est celle de la comparaison des deux premiers éléments trouvés différents. La comparaison de deux n-uplets s'effectue d'abord sur leur longueur, et à longueur égale sur la comparaison des deux premiers éléments trouvés différents. Le prédicat de comparaison est le suivant:
term_cmp(X, Y, V)
Compare les termes X et Y, unifie V avec l'entier -1 si X précède Y, 1 si Y précède X, 0 si les termes X et Y sont formellement égaux. Quelques exemples:
> term_cmp(1e0,1,V);
{V=-1}
> term_cmp(foo,zebra,V);
{V=-1}
> term_cmp(short,short,V);
{V=0}
> term_cmp(shorter,short,V);
{V=1}
> term_cmp(foo(a),foo(b),V);
{V=-1}
> term_cmp(foo(aa),foo(bb),V);
{V=-1}
> term_cmp(X,X,V);
{V=0}
> term_cmp(Y,X,V);
{V=-1}
> term_cmp(_,_,V);
{V=-1}
> term_cmp("foo",foo,V);
{V=1}
> term_cmp(1.2.3.nil,1.1.3.4.nil,V);
{V=1}
> term_cmp(1.2.nil,<1,2>,V);
{V=-1}
> term_cmp(1.2.nil,<X>,V);
{V=1}
>
term_cmpv(X, Y, V)
Compare les termes X et Y à la manière de term_cmp, mais sans prendre en compte les variables apparaissant dans les termes X et Y. Pour le prédicat
term_cmpv, deux variables distinctes sont considérées comme identiques.
Exemple:
> term_cmpv(foo(V1),foo(V2),V);
{V=0}
©PrologIA
R 4 - 16
Manuel de Référence
Deux prédicats de tri d'une liste sont fournis : sort/2, keysort/2. Pour effectuer ce tri, ils utilisent de manière interne le prédicat term_cmp/3 décrit ci-dessus.
sort(L1, L2)
L2 est unifiée avec la liste des éléments de L1 triés dans l'ordre croissant.
Dans cette liste, les éléments multiples ne sont conservés qu'une seule fois.
Exemple:
> sort(4.7.foo.3.4.1.nil,L);
{L=1.3.4.7.foo.nil}
keysort(L1, L2)
L2 est unifiée avec la liste des éléments de L1 triés dans l'ordre croissant.
Dans cette liste, les éléments multiples sont conservés. Exemple:
> keysort(4.7.foo.3.4.1.nil,L);
{L=1.3.4.4.7.foo.nil}
Ces mêmes prédicats admettent un argument supplémentaire qui désignera le prédicat utilisateur servant pour la comparaison des termes. Ce prédicat utilisateur devra être d'arité égale à 3. Il recevra les termes à comparer dans les 2 premiers et devra rendre dans le troisième argument le résultat de la comparaison (-1, 0 ou 1).
sort(L1, L2, C_ompar)
L2 est unifiée avec la liste des éléments de L1 triés dans l'ordre spécifié par le prédicat C_ompar. Dans cette liste, les éléments multiples ne sont conservés qu'une seule fois. Le prédicat sort/2 décrit précédemment n'est qu'un cas particulier de celui-ci, en donnant à l'argument C_ompar la valeur term_cmp.
Exemple:
> insert; compar_tuple(P1(X), P2(Y), R) -> term_cmp(X,Y,R);
;
> sort(aa(4).bb(7).cc(foo).dd(3).aa(4).ff(1).nil,L, compar_tuple);
{L=ff(1).dd(3).aa(4).bb(7).cc(foo).nil}
keysort(L1, L2, C_ompar)
L2 est unifiée avec la liste des éléments de L1 triés dans l'ordre spécifié par le prédicat C_ompar. Dans cette liste, les éléments multiples sont conservés. Le prédicat keysort/2 décrit précédemment n'est qu'un cas particulier de celui-ci, en donnant à l'argument C_ompar la valeur term_cmp. Exemple:
> insert; compar_tuple(P1(X), P2(Y), R) -> term_cmp(X,Y,R);
;
> keysort(aa(4).bb(7).cc(foo).dd(3).aa(4).ff(1).nil,L, compar_tuple);
{L=ff(1).dd(3).aa(4).aa(4).bb(7).cc(foo).nil}
A!ociation
Prolog
HERITAGE
©PrologIA

Public link updated
The public link to your chat has been updated.