- •Глава 1. Введение в пролог
- •1. Декларативные и процедурные языки программирования
- •2. Пролог и логика предикатов. Внешние цели
- •3. Управление программой. Подцели. Механизм сопоставления
- •4. Внутренние подпрограммы унификации
- •Глава 2. Внутренние цели. Механизм возврата
- •1. Структура пролог-программы
- •2. Использование внутренних целей
- •3. Встроенный предикат fail
- •4. Сокращенные варианты внутренних запросов
- •5. Использование в запросах анонимных переменных
- •6. Механизм возврата
- •Глава 3. Типы данных и арифметика Turbo Prolog
- •1. Стандартные типы данных
- •2. Структуры, простые и составные
- •3. Структурные диаграммы
- •4. Использование в запросах анонимных переменных
- •5. Использование альтернативных доменов
- •6. Арифметика в Turbo Prolog
- •Глава 4. Предикат отсечения (!). Программирование альтернатив. Правила повтора
- •1. Повторения и возвраты
- •2. Отсечение (!)
- •3. Программирование альтернатив
- •4. Правило повтора
- •Глава 5. Методы организации рекурсии
- •1. Простая рекурсия
- •2. Метод обобщенного правила рекурсии
- •3. Граничное условие рекурсии. Нисходящая и восходящая рекурсии
- •4. Программа о подсчете числа точек
- •Глава 6. Списки
- •1. Основные понятия
- •2. Списки и турбо-пролог
- •3. Атрибуты списка
- •4. Внутреннее представление списков
- •5. Применение списков в программе
- •6. Метод разделения списка на голову и хвост
- •7. Поиск элемента в списке
- •8. Присоединение списка
- •9. Добавление и удаление элемента
- •10. Подсписок
- •11. Перестановки списка
- •Глава 7. Сортировка списков
- •1. Разделение списка на два
- •2. Сортировка списков методом вставки
- •3. Быстрая сортировка
- •4. Быстрая сортировка_1
- •5. Компоновка данных в список
- •Глава 8. Программирование алгоритмов с возвратом. Представление графов в turbo prolog
- •1. Задача о весах
- •2. Представление графов в turbo prolog
- •3. Поиск пути на неориентированном графе
- •4. Поиск гамильтоновых циклов
- •5. Поиск пути минимальной стоимости
- •Глава 9. Динамическая база данных
- •1. Турбо-пролог и реляционные базы данных
- •2. Описание предикатов динамических бд
- •3. Встроенные предикаты asserta, assertz, retract, retractall, save, consult
- •4. Создание динамической базы данных
- •5. Обсуждение проекта базы данных
- •6. Создание базы данных
- •7. Написание программных модулей
- •Глава 10. Глобальные переменные в turbo prolog
- •1. Модификация базы данных
- •2. Накопление результатов с помощью вынуждаемого возврата
- •3. Подсчет членов парторганизации
- •4. Поиск пути минимальной стоимости от a до z
- •Библиографический список
- •Оглавление
8. Присоединение списка
Слияние двух списков в третий принадлежит к числу наиболее полезных при работе со списками операций. Этот процесс обычно называют присоединением одного списка к другому.
В качестве примера рассмотрим две переменные,L1 и L2, представляющие списки. Переменные имеют значения [1,2,3] и [4,5]. Назовем их входными списками. Предикат, присоединящий L2 к L1 и создающий выходной список L3, назовем concat.
Весь процесс можно представить себе в виде такой совокупности действий:
1. Список L3 вначале пуст.
2. Элементы списка L1 пересылаются в L3, теперь значением L3 будет [1,2,3].
3. Элементы списка L2 пересылаются в L3, в результате чего тот принимает значение [1,2,3,4,5].
Структура правила для выполнения этих действий достаточна проста:
concat([],L,L).
concat([N|L1],L2,[N|L3]) :-
concat(L1,L2,L3).
Поясним теперь, как будет функционировать это правило, если на вход подать списки L1=[1,2,3] и L2=[4,5]. Сначала Турбо-Пролог пытается удовлетворить первый вариант правила: concat([],L,L). Для того чтобы удовлетворить это правило, первый объект предиката concat нужно сделать пустым списком. Вначале же предикат concat имеет форму
concat([1,2,3],[4,5],L3)
Отметим, что третий, выходной список в этой форме пока еще не определен. Внутренний процесс унификации Турбо-Пролога, пытаясь удовлетворить второе правило concat, раскручивает цепочку рекурсий до тех пор, пока не обнуляет первый список.
ЭЛЕМЕНТЫ ПЕРВОГО СПИСКА ПРИ ЭТОМ ПОСЛЕДОВАТЕЛЬНО ПЕРЕСЫЛАЮТСЯ В СТЕК. Стек, логическая структура данных в памяти компьютера, обеспечивает временное хранение этих элементов.
Когда первый объект предиката concat окажется пустым списком, становится возможным применение первого варианта правила. Третий список при этом означивается вторым.
Такой процесс можно пояснить при помощи двух состояний concat, до и после применения первого варианта правила:
concat([],[4,5],_)
concat([],[4,5],[4,5])
В данный момент процедуры унификации Турбо-Пролога полностью удовлетворили это правило, и Турбо-Пролог начинает сворачивать рекурсивные вызовы второго правила:
concat([N|L1], L2, [N|L3]) :-
concat(L1,L2,L3).
Извлекаемые при этом из стека элементы помещаются один за другим в качестве головы к первому и третьему спискам.
Следует особо отметить, что элементы излекаются в обратном порядке (это стек!), и что значение извлеченного из стека элемента присваивается переменной N одновременно в [N|L1] и [N|L3]. Шаги данного процесса можно представить так:
concat([],[4,5],[4,5])
concat([3],[4,5],[3,4,5])
concat([2,3],[4,5],[2,3,4,5])
concat([1,2,3],[4,5],[1,2,3,4,5])
Присвоение элементов стека происходит рекурсивно до тех пор, пока стек не будет пуст. В результате список L3 будет содержать элеметы обоих входных списков — [1,2,3,4,5].
Программа 6.4 «Присоединение списка» демонстрирует применение данного метода. Внешней целью для программы может служить ранее разобранный пример:
concat([1,2,3],[4,5],L)
/* Программа 6.4 «Присоединение списка». */
/* Назначение: слияние двух списков. */
domains
list = integer *
predicates
concat(list,list,list)
clauses
concat([],L,L).
concat([N|L1], L2, [N|L3]) :-
concat(L1,L2,L3).
/* Конец программы */