Clauses. Length_of([_|T], L) :- length_of(T, TailLength)

length_of([], 0).

length_of([_|T], L) :- length_of(T, TailLength),

L = TailLength + 1.

Поглянемо спочатку на другу фразу. Так, length_of [_ ,|T] порівнює любий непустий список, прив`язуючи Tдо хвосту списка. Значення голови не суттєво, ЕОМ буде її рахувати як один елемент.

Так ціль

goal: length_of([1,2,3], L) ,

використовуючи другу фразу, зв'яже з T значення [2,3]. Наступний крок - обчислити довжину T. Коли це зроблено, не важливо як, тоді TailLength отримає значення 2, і ЭВМ потім зможе добавити до неї 1 та прив'язатиL до 3.

Для того, щоб визначити довжину [2,3] рекурсивно викличеться length_of([2,3], TailLength. Ця ціль зрівнює другу фразу, прив'язуючи - [3] до T . Тепер виникає задача, як знайти довжину [3], яка дорівнює 1, а потім добавить1, щоб отримати довжину [2,3], яка буде 2. І так далі і тому подібно. Тому length_of знов викличе себе рекурсивно, щоб отримати довжину списку [3]. Хвіст для [3] рівний [ ], тому T зв'яжеться з [], і задача зараз полягає в тому , щоб знайти довжину [], потім додати до неї 1, і знайти довжину [3]. На цей раз це зробити легко. Ціль length_of([], Tail Length зрівнюючи першу фразу, зв'яже TailLengthз 0. Тепер ЭОМ може додати 1до неї, отримуючи довжину списку [3] і повернутися до фрази виклику. Яка , в свою чергу , прибавить знову 1 , отримуючи довжину [2,3] і повернеться до фрази, яка викликала її; ця початкова фраза прибавить знову 1 , знаходячи довжину списку [1,2,3].

Малюнок 8.1 показує дійсний процес обчислення довжини списку. Ми використали тут різні змінні, щоб підкреслити той факт, що змінні з одинаковими іменами в різних фразах , або різних викликах однієї і тієї ж фрази, будуть різними.

length-of([1,2,3],L1)

length-of([2,3],L2)

length-of([3],L3)

length-of([],0)

L3 = 0 + 1 = 1

L2 = L3+ 1 = 2

L1 = L2+ 1 = 3

Мал.8.1.Обчислення довжини списку.

8.2.3.Іще один варіант підрахунку довжини списку.

Як ви бачите, предикат length_of не є хвостовою рекурсією. Чи можливо створити рекурсивно-хвостовий предикат визначення довжини списку? Можливо, але для цього потрібно прикласти певні зусилля.

Проблема з length_ of заключається в тому, що ми не можемо обчислити довжину списку, пока не підрахуємо довжину хвоста. Та все ж така можливість мається. Використаємо предикат з трьома аргументами.

- Перший є список, котрий ЕОМ буде читати при кожному виклику, поки він не стане пустим.

- Другий є вільним аргументом, який в кінці роботи буде визначати результат.

- Третій є лічильником, котрий починається з 0 і збільшується з кожним викликом. В кінці лічильник можна уніфікувати з незв'язаним результатом.

Наступна програма реалізує наш підхід.

Domains

list = integer*

Predicates

Length_of(list, integer, integer)

Наши рекомендации