меньше(Х,Y):- name(X,L), name(Y,M), меньше _1(L,M).
меньше_1([], [_|_]).
меньше_1([X|_],[Y|_]):- Х‹Y.
меньше_1([P|Q], [R|S]):- P = R, меньше_1(Q,S).
Заметим, что третье правило для меньше_1можно было бы записать более естественно так:
меньше_1([H|Q], [H|S]):- меньше_l(Q,S).
Упражнение 3.1.Подумайте, какое еще утверждение необходимо добавить к этому определению так, чтобы предикат был истинен и в том случае, когда два слова совпадают. В результате получится предикат, проверяющий, меньше или равен первый аргумент второму по алфавиту. Указание: обратите внимание на условие (4), приведенное выше, и вставьте утверждение, обрабатывающее это условие.
Упражнение 3.2.Почему в первом утверждении для предиката меньше_1в качестве второго аргумента использован список [_|_]? Почему недостаточно использовать список [.]?
3.6. Использование предиката присоединить и спецификация деталей
Предикат присоединить, обрабатывающий списки, используется для создания нового списка, являющегося результатом соединения двух других списков. Например, верен следующей факт:
присоединить([а,b,с], [3,2,1], [а,b,с,3,2,1]).
Предикат присоединитьнаиболее часто используется для создания нового списка в результате конкатенации двух других списков, как в следующем примере:
?- присоединить ([alpha,beta],[gamma,delta],X).
X=[alpha, beta, gamma, delta]
Но он может также использоваться и другим способом;
?- присоединить(Х,[b,c,d],[a,b,c,d]). Х=[а]
Предикат присоединитьимеет следующее определение;
присоединить([],L,L).
присоединить([Х|L1],L2,[Х|L3]):- присоединить (L1,L2,L3).
Выход на граничное условие происходит, когда первый аргумент является пустым списком. Любой список, присоединенный к пустому списку, дает тот же самый список. Во всех других случаях будет выполняться второе правило, смысл которого можно описать словами следующим образом:
1. Первый элемент первого списка (X)всегда будет и первым элементом третьего списка.
2. Хвост третьего аргумента (L3)всегда будет представлять результат присоединения второго аргумента (L2)к хвосту первого списка (L1).
3. Для присоединения одного списка к другому, о чем шла речь в пункте 2, необходимо использовать предикат присоединить.
4. Так как при каждом обращении к правилу удаляется голова списка, являющегося первым аргументом, то постепенно этот список будет исчерпан и станет пустым, так что произойдет выход на граничное условие.
В дальнейших примерах будут встречаться ссылки на предикат присоединитьс необходимыми дополнительными пояснениями. В последующих главах мы обсудим различные свойства и применения этого предиката. Но сначала давайте применим его в другом простом примере рекурсии.
Предположим, что мы работаем на заводе, выпускающем велосипеды, и нам необходимо хранить спецификацию деталей велосипеда. Для того чтобы собрать велосипед, надо знать, какие детали заказать поставщикам. Каждая деталь велосипеда может состоять из более мелких элементов – поддеталей, например каждое колесо имеет спицы, обод и ступицу. Более того, ступица может состоять из оси и шестеренок. Давайте рассмотрим базу данных, организованную в виде дерева, которая позволит нам делать запросы о деталях, необходимых для изготовления некоторой части велосипеда. В одной из следующих глав предложенная здесь программа будет улучшена, с тем чтобы позволить вычислять, сколько экземпляров каждой детали нам потребуется.
Имеются два типа объектов, которые используются для изготовления велосипеда. Это узлы и детали. Каждый узел состоит из некоторого числа деталей, подобно тому как колесо состоит из спиц, обода и ступицы. Детали не имеют еще более мелких частей – они просто соединяются друг с другом, образуя узлы.
Можно представить детали как факты следующим образом:
деталь(обод). деталь(спица).
деталь(задняя_рама). деталь(руль).
деталь(шестерни). деталь(болт).
деталь(гайка). деталь(вилка).
Естественно, что это далеко не полный список деталей, необходимых для сборки велосипеда, но приведенные факты показывают основную идею. Узел может быть представлен именем узла, за которым следует список входящих в него деталей с указанием их количества. Например, следующий факт означает, что велосипед- это узел, состоящий из двух колес и рамы:
узел(велосипед, [колесо, колесо, рама]).
Ниже представлена база данных узлов, необходимых для нашего упрощенного велосипеда:
Читать дальше