Buscar..


Introducción

Las listas de diferencias en Prolog denotan el concepto de conocer la estructura de una lista hasta cierto punto . El resto de la lista puede dejarse sin consolidar hasta la evaluación completa de un predicado. Una lista donde se desconoce su final se conoce como una lista abierta , terminada por un agujero . Esta técnica es especialmente útil para validar sintaxis complejas o gramáticas.

Las conocidas gramáticas de cláusula definida (DCG) utilizan listas de diferencias para operar bajo el capó.

Uso básico

Consideremos el predicado sumDif/2 , verificado si la estructura de una lista coincide con varias restricciones. El primer término representa la lista para analizar y el segundo término otra lista que contiene la parte de la primera lista que desconocemos para nuestras restricciones.

Para la demostración, sumDif/2 reconoce una expresión aritmética para sumar n enteros.

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

Sabemos que el primer elemento de la lista para validar es un entero, aquí ilustrado con X , seguido del símbolo de la suma ( + ). El resto de la lista que aún debe procesarse más adelante ( OpenList ) se deja sin validar en ese nivel. Hole representa la parte de la lista que no necesitamos validar.

Demos otra definición del predicado sumDif/2 para completar la validación de la expresión aritmética:

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

Esperamos un entero llamado X directamente al inicio de la lista abierta. Curiosamente, el resto del Hole de la lista se desconoce y ese es el propósito de las listas de diferencias: la estructura de la lista se conoce hasta cierto punto.

Finalmente, la pieza faltante viene cuando se evalúa una lista:

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

Esto es cuando se usa el predicado que menciona el final de la lista, aquí [] , indica que la lista no contiene elementos adicionales.

Evaluar una expresión aritmética.

Definamos una gramática que nos permita realizar adiciones, multiplicaciones con el uso de paréntesis. Para agregar más valor a este ejemplo, vamos a calcular el resultado de la expresión aritmética. Resumen de la gramática:

expresión → veces
expresión → veces '+' expresión
tiempos → elemento
tiempos → elemento '*' veces
elemento → "entero"
elemento → '(' expresión ')'

Todos los predicados tienen una aridad de 3, porque necesitan abrir la lista, el agujero y el valor de la expresión aritmética.

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]).

Para explicar adecuadamente el principio de los agujeros y cómo se calcula el valor, tomemos la segunda expression cláusula:

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

La lista abierta es denotada por el predicado OpenList . El primer elemento a validar es lo que viene antes del símbolo de adición ( + ) . Cuando se valida el primer elemento, es seguido directamente por el símbolo de adición y por la continuación de la lista, llamada Hole1 . Sabemos que Hole1 es el siguiente elemento para validar y puede ser otra expression , por Hole1 tanto, Hole1 es el término dado a la expression predicado.

El valor siempre está representado en el primer término. En esta cláusula, se define por la suma del Value1 (todo antes del símbolo de adición) y el Value2 (todo después del símbolo de suma).

Finalmente, la expresión puede ser evaluada.

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


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow