Читаем Программирование на языке пролог полностью

Если совпадает, то наш список завершается успехом. Если нет, то мы проверяем, есть ли кличка в хвосте исходного списка. Это значит, что снова проверяется голова, но уже хвостасписка. Затем проверяется голова очередногохвоста списка. Если мы доходим до конца списка, который будет пустым списком, то наш поиск завершается неудачей: указанной клички в исходном списке нет.

Для того чтобы записать все это на Прологе, сначала надо установить, что между объектом и списком, в который этот объект может входить, существует отношение. Это отношение, называемое отношением принадлежности, представляет достаточно распространенное в повседневной жизни понятие. Так, мы говорим о людях, являющихся членами клубов, и о других тому подобных вещах. Для записи этого отношения мы будем использовать предикат принадлежит:целевое утверждение принадлежит(X, Y)является истинным («выполняется»), если терм, связанный с X, является элементом списка, связанного с Y. Имеются два условия, которые надо проверить для определения истинности предиката. Первое условие говорит, что Xбудет элементом списка Y, если X совпадает с головой списка Y. На Прологе этот факт записывается следующим образом:

принадлежит(X,[X |_]).

Эта запись констатирует, что X является элементом списка, который имеет X в качестве головы.Заметим, что мы использовали анонимную переменную '_' для обозначения хвоста списка. Это сделано потому, что мы никак не используем хвост списка в этом частном факте. Заметим, что данное правило могло бы быть записано и по-другому:

принадлежит(X,[Y|_]:- X = Y.

К этому моменту вы должны уже понимать, почему можно использовать Xсразу в двух местах в первой, более короткой, версии этого правила.

Второе, и последнее, правило говорит о том, что Xпринадлежит списку при условии, что он входит в хвост этого списка, обозначаемый через Y. И нет лучшего пути, чем использовать тот же самый предикат принадлежитдля того, чтобы определить, принадлежит ли Xхвосту списка! В этом и состоит суть рекурсии. На Прологе это выглядит так:

принадлежит(X,[_ |Y]):- принадлежит(X,Y).

и констатирует, что X является элементом списка, еслиX является элементом хвоста этого списка.Заметим, что мы использовали анонимную переменную '_', так как нас не интересует имя переменной, обозначающей голову списка. Два этих правила в совокупности определяют предикат для отношения принадлежности и указывают Прологу, каким образом просматривать список от начала до конца при поиске некоторого элемента в списке. Наиболее важный момент, о котором следует помнить, встретившись с рекурсивно определенным предикатом, заключается в том, что прежде всего надо найти граничные условияи способ использования рекурсии.

Для предиката принадлежитв действительности имеются два типа граничных условий. Либо объект, который мы ищем, содержится в списке, либо он не содержится в нем. Первое граничное условие для предиката принадлежитраспознается первым утверждением, которое приведет к прекращению поиска в списке, если первый аргумент предиката принадлежитсовпадает с головой списка, соответствующего второму аргументу. Второе граничное условие встречается, когда второй аргумент предиката принадлежитявляется пустым списком.

Как мы можем убедиться в том, что граничные условия будут когда-либо удовлетворены? Для этого необходимо обратить внимание на то, как используется рекурсия во втором правиле для предиката принадлежит. Заметим, что каждый раз, когда при поиске соответствия для целевого предиката принадлежитпроисходит рекурсивное обращение к тому же предикату, новая цель формируется для более короткогосписка. Хвост списка всегда является более коротким списком, чем исходный список. Очевидно, что рано или поздно произойдет одно из двух событий: либо произойдет сопоставление с первым правилом для принадлежит, либо в качестве второго аргумента принадлежитбудет задан список длины 0, т. е. пустой список. Как только возникнет одна из этих ситуаций, прекратится рекуррентное порождение целей для предиката принадлежит. Первое граничное условие распознается фактом, который не вызывает порождения новых подцелей. Второе граничное условие не распознается ни одним из утверждений для принадлежит, так что процесс поиска сопоставимого элемента списка для целевого утверждения принадлежит закончится неудачей. Это демонстрирует следующий пример на Прологе:

принадлежит(Х, [X | _]).

принадлежит(Х,[_|Y]):- принадлежит (X,Y).

?- принадлежит(d,[a,b,с,d,e,f,g]).

да

?- принадлежит(2,[3,a,4,f]).

нет

Предположим, мы введем вопрос

?- принадлежит(clugatе,[curraugh_tiр,music_star,раrk_mill, ortland]).

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже