
2.7. Составные списки
Список целых может быть просто объявлен как список_целых = integer*
Также просто можно объявить список вещественных чисел, список символов или список строк.
Однако, часто возникает необходимость хранить в рамках одного списка комбинацию значений разных типов, например:
[2,3,5.12,[пища,"сладкое"],"новое"]
Составные списки - это списки, которые содержат элементы более чем одного типа. Для работы с многотипными списками нужны специальные объявления, потому что Visual-Пролог требует, чтобы все элементы списка принадлежали одному и тому же домену. Чтобы создать многотипный список в Прологе, необходимо использовать функторы, потому что домен может содержать в качестве аргументов функторов более одного типа данных.
Ниже приводится пример объявления domains для списка, который может содержать данные типа symbol, integer, char или string, или список данных любого из этих типов. Объявление списка должно иметь такой функтор, как приведенный, а затем должно быть объявлено рекурсивно. Необходимое для создания многотипного списка объявление domains может иметь следующий вид:
domains /* функторы - сп, s, ц, сим и стр */
с_список = сп(список); s(symbol); ц(integer);
сим(char); стр(string)
список = с_список*
Список [2,9,[пища,"сладкое"],"новое"] на Visual-Прологе можно было бы представить так:
[ц(2),ц(9),сп([s(пища),стр("сладкое")]),стр("новое")]
2.8. Резюме
1. Списки - это объекты, которые могут содержать произвольное число элементов; они объявляются путем добавления к концу ранее определенного домена звездочки.
2. Список - это рекурсивный составной объект, состоящий из головы и хвоста. Голова - это первый элемент, а хвост - это остальная часть списка (без первого элемента). Хвост списка - это всегда список; голова списка - это элемент. Список может содержать нуль или более элементов; пустой список записывается [].
3. Элементами списка может быть все, что угодно, включая другие списки; все элементы списка должны принадлежать одному и тому же домену. Объявление domains для таких элементов должно иметь вид:
domains
список_элементов = элементы*
элементы = ...
где элементы соответствуют одному из стандартных доменов
(integer, real и т.д.) или набору альтернатив, помеченных разными функторами (ц(integer); вщ(real); s(symbol); и т.д.). Смешивать типы в списке в Visual-Прологе нельзя.
4. Для явного выделения головы и хвоста списка можно использовать разделители (запятые, [ и |); например, список
[a,b,c,d]
может быть записан как
[a|[b,c,d]] или [a,b|[c,d]] или [a,b,c|[d]] или
[a|[b|[c,d]]] или [a|[b|[c|[d]]]] или даже
[a|[b|[c|[d|[]]]]]
5. Обработка списка заключается в рекурсивном изъятии головы списка (и, как правило, выполнении с этим элементом какихлибо действий) до тех пор, пока список не станет пустым.
6. Одно важное свойство Пролога, присущее некоторым предикатам, называется взаимозаменяемостью неизвестных.
7. Классические предикаты Пролога, относящиеся к обработке списков - "принадлежит" и "присоединить" - позволяют проверять, есть ли элемент в списке, а также проверять, входит ли один список в другой (или присоединять один список к другому),соответственно.
8. Структура потока предиката - это состояние его аргументов, когда этот предикат вызывается; аргументы могут быть входными параметрами (i), которые связываются или получают значения, или выходными параметрами (o), которые являются свободными.
9. В Visual-Прологе предусмотрен встроенный предикат findall, в качестве одного из аргументов которого выступает цель. Он собирает все решения для этой цели в один список.
10. Составные списки - это списки, содержащие элементы более чем одного типа. Ввиду того, что Visual-Пролог требует принадлежности всех элементов списка одному домену, для создания списка с элементами нескольких типов используются функторы; домен может содержать более одного типа данных в качестве аргументов функторов.
2.9 Задание
1. Создать список, состоящий из значений первых аргументов предикатов, которые были сформированных в л.р.№1.
2. Распечатать список
3. Подсчитать количество элементов в списке.
4. Найти в заданном списке указанный элемент.
Дополнительные задания на 5.
1. Написать предикат, который из списка целых чисел удалит отрицательные числа, результат будет сформирован в новом списке.
2. Написать предикат, который соединит два списка целых чисел в один.
3. Написать предикат для удаления из списка заданного элемента.
4. Написать предикат, который из списка целых чисел удалит числа больше заданного.