Recherche…


Introduction

Les listes de différences de Prolog désignent le concept pour connaître la structure d'une liste jusqu'à un point . Le reste de la liste peut être laissé libre jusqu'à l'évaluation complète d'un prédicat. Une liste dont la fin est inconnue est appelée liste ouverte , terminée par un trou . Cette technique est particulièrement utile pour valider des syntaxes complexes ou des grammaires.

Le bien connu Grammars Clause définie (DCG) utilise des listes de différences pour fonctionner sous le capot.

Utilisation de base

Considérons le prédicat sumDif/2 , vérifié si la structure d'une liste correspond à plusieurs contraintes. Le premier terme représente la liste à analyser et le second terme une autre liste contenant la partie de la première liste inconnue de nos contraintes.

Pour la démonstration, sumDif/2 reconnaît une expression arithmétique pour résumer n entiers.

sumDif([X, +|OpenList], Hole) :-
    integer(X),
    sumDif(OpenList, Hole).

Nous savons que le premier élément de la liste à valider est un entier, ici illustré par X , suivi du symbole de l'addition ( + ). Le reste de la liste qui doit encore être traité ultérieurement ( OpenList ) est laissé non validé à ce niveau. Hole représente la partie de la liste que nous n'avons pas besoin de valider.

Donnons une autre définition du prédicat sumDif/2 pour compléter la validation de l'expression arithmétique:

sumDif([X|Hole], Hole) :-
    integer(X).

Nous attendons un entier appelé X directement au début de la liste ouverte. Il est intéressant de noter que le reste de la liste Hole reste inconnu et que les listes de différences servent à l’objectif: la structure de la liste est connue jusqu’à un certain point.

Enfin, la pièce manquante vient quand une liste est évaluée:

?- sumDif([1,+,2,+,3], []).
true

C'est lorsque le prédicat est utilisé que la fin de la liste est mentionnée, ici [] , indique que la liste ne contient pas d'éléments supplémentaires.

Evaluer une expression arithmétique

Définissons une grammaire permettant d'effectuer des additions, des multiplications avec l'utilisation de parenthèses. Pour ajouter plus de valeur à cet exemple, nous allons calculer le résultat de l'expression arithmétique. Résumé de la grammaire:

expression → fois
expression → fois expression '+'
times → element
times → element '*' times
element → "entier"
element → '(' expression ')'

Tous les prédicats ont une arité de 3, car ils doivent ouvrir la liste, le trou et la valeur de l'expression arithmétique.

expression(Value, OpenList, FinalHole) :-
    times(Value, OpenList, FinalHole).

expression(SumValue, OpenList, FinalHole) :-
    times(Value1, OpenList, ['+'|Hole1]),
    expression(Value2, Hole1, FinalHole),
    plus(Value1, Value2, SumValue).

times(Value, OpenList, FinalHole) :-
    element(Value, OpenList, FinalHole).

times(TimesValue, OpenList, FinalHole) :-
    element(Value1, OpenList, ['*'|Hole1]),
    times(Value2, Hole1, FinalHole),
    TimesValue is Value1 * Value2.

element(Value, [Value|FinalHole], FinalHole) :-
    integer(Value).

element(Value, ['('|OpenList], FinalHole) :-
    expression(Value, OpenList, [')'|FinalHole]).

Pour bien expliquer le principe des trous et comment la valeur est calculée, prenons la deuxième expression clause:

expression(SumValue, OpenList, FinalHole) :-
    times(Value1, OpenList, ['+'|Hole1]),
    expression(Value2, Hole1, FinalHole),
    plus(Value1, Value2, SumValue).

La liste ouverte est désignée par le prédicat OpenList . Le premier élément à valider est ce qui précède le symbole d'addition ( + ) . Lorsque le premier élément est validé, il est directement suivi du symbole d'addition et de la suite de la liste, appelée Hole1 . Nous savons que Hole1 est l'élément suivant à valider et peut être une autre expression , donc Hole1 est alors le terme donné à l' expression prédicat.

La valeur est toujours représentée dans le premier terme. Dans cette clause, elle est définie par la somme de Value1 (tout avant le symbole de l’addition) et Value2 (tout après le symbole de l’addition).

Enfin, une expression peut être évaluée.

?- expression(V, [1,+,3,*,'(',5,+,5,')'], []).
V = 31


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow