На этом шаге мы рассмотрим поиск всех решений для цели сразу.
Преимущество рекурсии состоит в том, что, в отличие oт поиска с возвратом, она передает информацию (через параметры) от одного рекурсивного вызова к следующему. Поэтому рекурсивная процедура может хранить память о промежуточных результатах или счетчиках по мере того, как она выполняется.
Но есть одна вещь, которую поиск с возвратом может делать, а рекурсия - нет. Это поиск всех альтернативных решений в целевом утверждении. Может оказаться, что вам нужны все решения для целевого утверждении, и они необходимы все сразу, как часть единой сложной составной структуры данных. Встроенный предикат использует целевые утверждения в качестве одного из своих аргументов и собирает все решения для этого целевого утверждения в единый список. У предиката findall три аргумента:
domains name,address=string age=integer list=age* predicates person(name,address,age) sumlist(list,age,integer) clauses sumlist([],0,0). sumlist([H |T],Sum,N):- sumlist(T,S1,N1), Sum=H+S1, N=1+N1. person("Sherlock Holmes","22B Baker Street",42). person("Pete Spiers","Apt. 22, 21st Street", 36). person("Mary Darrow", "Suite 2, Omega Home", 51). goal findall(Age,person(_, _, Age),L), sumlist (L,Sum,N), Ave=Sum/N, write("Average=", Ave),nl.
Результат работы программы можно посмотреть на рис.1
Рис.1. Результат работы программы pro47_1.pro
Предложение findall в этой программе создает список L, в котором собраны все возвраты, полученные из предиката person. Если бы вы захотели собрать список из всех людей, которым 42 года, то вам следовало бы выполнить следующее подцелевое утверждение:
findall(Who,person(Who,_,42),List)
slist=string*
На следующем шаге мы рассмотрим составные списки.