Поиск…


Вступление

Разностные списки в Прологе означают концепцию, чтобы знать структуру списка до точки . Оставшийся список можно оставить без привязки до полной оценки предиката. Список, где его конец неизвестен, называется открытым списком , заканчивающимся отверстием . Этот метод особенно полезен для проверки сложных синтаксисов или грамматик.

Известные грамотные грамматики (DCG) используют разностные списки для работы под капотом.

Основное использование

Рассмотрим предикат sumDif/2 , проверенный, если структура списка соответствует нескольким ограничениям. Первый термин представляет собой список для анализа, а второй термин - другой список, который содержит часть первого списка, который неизвестен нашим ограничениям.

Для демонстрации sumDif/2 распознает арифметическое выражение для суммирования n целых чисел.

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

Мы знаем, что первым элементом списка для проверки является целое число, здесь иллюстрируется X , за которым следует символ сложения ( + ). Оставшийся список, который еще предстоит обработать позже ( OpenList ), остается неизменным на этом уровне. Hole представляет собой часть списка, которую нам не нужно проверять.

Давайте дадим другое определение предиката sumDif/2 для завершения проверки арифметического выражения:

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

Мы ожидаем, что целое число называется X непосредственно в начале открытого списка. Интересно, что оставшаяся часть списка Hole остается неизвестной, и это целая цель Разностных списков: структура списка известна до определенной точки.

Наконец, недостающая часть появляется, когда оценивается список:

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

Это когда предикат используется, когда упоминается конец списка, здесь [] указывает, что список не содержит дополнительных элементов.

Оценить арифметическое выражение

Давайте определим грамматику, позволяющую нам выполнять дополнения, умножения с использованием скобок. Чтобы добавить больше значения в этот пример, мы собираемся вычислить результат арифметического выражения. Резюме грамматики:

выражение → раз
выражение → times '+' выражение
раз → элемент
раз → элемент '*' раз
элемент → "целое число"
элемент → '(' выражение ')'

Все предикаты имеют arity of 3, потому что им нужно открыть список, отверстие и значение арифметического выражения.

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

Чтобы правильно объяснить принцип дыр и как вычисляется значение, давайте возьмем expression второго предложения:

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

Открытый список обозначается предикатом OpenList . Первым элементом для проверки является то, что предшествует символу добавления ( + ) . Когда первый элемент проверяется, за ним сразу следует символ добавления и продолжением списка, называемого Hole1 . Мы знаем, что Hole1 является следующим элементом для проверки и может быть другим expression , поэтому Hole1 тогда является термином, заданным для expression предиката.

Значение всегда представляется в первом члене. В этом разделе он определяется суммой Value1 (все перед символом добавления) и Value2 (все после символа добавления).

Наконец, выражение можно оценить.

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


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow