1.4.3. РЕКУРСИЯ
Определение функции может содержать как вызовы библиотечных функций, так и вызовы функций, определяемых в программе. В частности, функция может вызывать и саму себя (либо непосредственно, либо через другие определяемые функции). В этом случае будем говорить, что определение функции является рекурсивным.
Необходимость в рекурсивных определениях обычно возникает в тех случаях, когда функция должна быть определена для бесконечного множества аргументов и при этом размер аргумента может быть произвольно большим.
Рассмотрим, например, следующую задачу. Пусть требуется определить функцию Reverse, которая "переворачивает" выражение, т.е. переставляет термы аргумента в обратном порядке. А именно, если на вход поступает объектное выражение видаOt1 Ot2 ... Otn
где Ot1, Ot2, ..., Otn - некоторые объектные термы, то на выходе должно получиться объектное выражениеOtn ... Ot2 Ot1
Если бы длина входного выражения была ограничена, например, если бы мы знали, что n<=3, можно было бы разобрать четыре разных случая и написать следующее определение функции:
|
Можно, однако, преодолеть это затруднение с помощью рекурсии. В данном случае можно рассуждать следующим образом. Рассмотрим входное выражение
Ot1 Ot2 ... Otn
Если n=0, то результатом должно быть пустое выражение. Если же n>=1, то можно свести исходную задачу к более простой: отбросить первый терм входного выражения, получив выражение длины n-1,Ot2 ... Otn
и перевернуть это более короткое выражение. ПолучитсяOtn ... Ot2
Теперь ясно, что если к этому выражению приписать справа Ot1, мы как раз и получим желаемый результатOtn ... Ot2 Ot1
Эти рассуждения приводят нас к следующему рекурсивному определению функции Reverse :
|
|
Oe = Oe1 Oe2
Теперь мы можем перевернуть каждое из выражений Oe1 и Oe2 по отдельности. Пусть при этом получатся выражения Oe1' и Oe2' соответственно. Тогда ясно, чтоOe2' Oe1'
равно результату обращения исходного выражения Oe. Если Рефал реализован на многопроцессорной машине таким образом, что обращение выражений Oe1 и Oe2 можно выполнять одновременно, оказывается, что выгодно, чтобы Oe1 и Oe2 были приблизительно одинаковой длины. Тогда получаем следующий вариант описания функции, в котором используются библиотечные функции из модулей ACCESS и ARITHM:
|