refal Prolog programming
Продолжаем играться с прологом и рефалом. На этот раз добавим к нашей реализации рефаловского сопоставления по образцу жадные(greedy) переменные.
Напомню, что в языке Рефал есть такая интересная возможность, как паттерн-матчинг с так сказать "опережающим" поиском. (про Рефал писали, например, в недавнем номере ПФП). Т.о., предикат списка-палиндрома в рефале можно описать так:
—
Pal {
s.1 e.2 s.1 = <Pal e.2> ;
s.1 = True ;
= True;
e.1 = False ;
}
—
где e.
переменные могут принимать любое значение подсписка (пустой, из одного или более элементов), а s. — один элемент списка.
Мы пытаемся построить с помощью пролога такой DSL, который позволил бы использовать рефаловское сопоставление по образцу (попутно добавив несколько других интересных плюшек :).
Пример предиката для определения, является ли список палиндромом, на нашем DSL приводился в одном из предыдущих постов. Сейчас же приведем несколько примеров работы с жадными переменными:
==
?- re([e(A), e(B)], [1,2,3]).
A = [],
B = [1, 2, 3].
?- re([e*(A), e(B)], [1,2,3]).
A = [1, 2, 3],
B = [].
==
Как видите, во втором примере "жадная" переменная A захватила максимально допустимое паттерном число элементов. Еще пример:
==
?- re([e(A), s(B), e(C)], [1,2,3]).
A = [],
B = s(1),
C = [2, 3].
?- re([e*(A), s(B), e(C)], [1,2,3]).
A = [1, 2],
B = 3,
C = [].
==
Добавим еще один тип переменных — непустые e-переменные. Назовем их "e+" переменные. Пример использования:
==
?- re([e+(A), e(B)], [1,2,3]).
A = [1],
B = [2, 3].
?- re([e*(A), e+(B)], [1,2,3]).
A = [1, 2],
B = [3].
==
И, в заключении, самый интересный, на мой взгляд, пример. Не забываем, что под капотом у нас пролог:
==
?- re([A,B], [1,2,3]).
A = s(1),
B = e([2, 3]).
==
В этом примере мы не указали тип переменных A и B, и пролог подставляет возможные значения типов переменных сам! Подставляет так, чтобы удовлетворить ограничению в две переменные. (замечу, что предлагается только 1 вариант, т.к. в реализации нашего DSL каждое правило оканчивается отсечением).
Вот такой вот получился наколеночный рефал :)
p.s. исходный код этой поделки на
pastebin.com