Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
AlgStr / Библиотека / POSIBNIK / ПРОГР НА ПРОЛОГЕ.doc
Скачиваний:
51
Добавлен:
23.03.2015
Размер:
670 Кб
Скачать

4.7.3. Метод поділу списку на голову і хвіст (псгх)

Природно обробляти списки, починаючи з голови. Для поділу списку на голову і хвіст можна використати символ “|”. Якщо зіставити список [Head | Tail] з іншим списком, то Head одержить значення елемента, що розташований у голові списку, а Tail – значення хвоста. Слід зазначити, що ціль [Head | Tail] може зіставитися тільки з непорожнім списком. Тому наша процедура друку списку повинна складатися мінімум із двох тверджень. Одне твердження буде визначати наші дії для порожнього списку, а інше – для непорожнього:

CLAUSES

друк_списку( [ ] ).

друк_списку( [Head | Tail] ):-

write(Head), nl,

друк_списку( Tail ).

Завдяки тому, що хвіст списку (Tail) є список, його можна обробити за допомогою цієї ж процедури (з використанням рекурсії). Оскільки операція поділу списку на голову і хвіст може застосовуватися до списків, що містять елементи різного доменного типу, то немає необхідності реалізовувати кілька предикатів для друку списків різних доменних типів. Але описати їх у розділі PREDICATES необхідно з указівкою всіх доменних типів:

PREDICATES

друк_списку(список_цілих)

друк_списку(список_дійсних)

друк_списку(список_тварин)

Такі процедури, аргументами яких можуть бути об'єкти різних типів, у програмуванні прийнято називати поліморфними процедурами. Процедура друк_списку є саме така поліморфна процедура ще й тому, що предикат write у мові TP також є поліморфним.

Поцедура друку списку реалізувалась рекурсивно. І це невипадково. Визначення списку є також рекурсивне. А для рекурсивних структур даних найбільш природний спосіб обробки – рекурсія. Для TP рекурсія до того ж і єдиний можливий спосіб обробки таких структур.

4.7.4. Списки списків

Як уже зазначалося компонентами списків можуть бути списки, причому списки різних доменних типів. Визначимо, наприклад, список, що складається зі списків цілих чисел, списків дійсних чисел і списків тварин. Щоб TP зміг відрізнити один вид списку від іншого, елементи цих списків і сам список слід описати зі спеціальним тэгом (ярличком). Це можна зробити, наприклад, у такий спосіб:

DOMAINS

llist = l(list); ц(integer); д(real); т(symbol)

list = llist *

CLAUSES

список_списків( [

l( [ ц(1), ц(5), ц(7)] ),

l( [ д(3.2), д(4.6), д(5.7), д(1.5) ]),

l( [ т(кішка), т(собака), т( кінь) ])

] ).

список_списків( [

l( [ ц(1), ц(5), ц(7)] ),

т(папуга), ц(9),

l( [ д(3.2), д(4.6), у(5.7), д(1.5) ]),

д(3.14),

l( [ т(кішка), т(собака), т( кінь) ])

] ).

Списки навіть можна чергувати зі скалярними елементами. Тобто llist – це список списків і скалярних елементів заданих доменних типів. Альтернативи при описі такого типу розділяються символом “;”.