Home > Software engineering >  Prolog - understanding recursive predicate returning list
Prolog - understanding recursive predicate returning list

Time:06-04

I am very new to Prolog and wondering if I could get some help in better understanding the below code. I understand the code relating to 'divides' and 'find_num', but I am having difficulty with wrapping my head around what is happening with 'check_list'. Any help in furthering my understanding would be greatly appreciated.

 divides(X, Y) :-
     X mod Y =:= 0.

 find_num(X, Y, Lout) :-
      findall(N, between(1, X, N), Lin),
      check_list(Lin, Y, Lout).

 check_list([], _, []).

 check_list([H | Tin], Y, [H | Tout]) :-
   divides(H, Y),
   check_list(Tin, Y, Tout).

 check_list([H | Tin], Y, Lout) :-
   \  divides(H, Y),
   check_list(Tin, Y, Lout).

CodePudding user response:

Let's look at a simpler predicate:

copy_list([],[]).
copy_list([H|Tin],[H|Tout]) :- copy_list(Tin,Tout).

If you pass in two identical lists then this predicate will succeed if they are equal. If you pass one list and one variable, either way around, then this will copy the list.

It's convention to put inputs on the left and outputs on the right.

Let's look at this query:

?- copy_list([1,2,3],Xs).

Internally Prolog (in my case SWI) replaces the variable Xs with an internal name, so the first call is copy_list([1, 2, 3], _52812). Prolog looks for a predicate match and finds copy_list([H|Tin],[H|Tout]). It then unifies and gets copy_list([1|2,3],[1|_55684]). It then tries to prove the body.

Its second call is copy_list([2,3],_55684). Prolog looks for a predicate match and finds copy_list([H|Tin],[H|Tout]). It then unifies and gets copy_list([2|3],[2|_69116]). It then tries to prove the body.

Its third call is copy_list([3],_69116). Prolog looks for a predicate match and finds copy_list([H|Tin],[H|Tout]). It then unifies and gets copy_list([3|[]],[3|_69734]). It then tries to prove the body.

On its forth call the empty list predicate copy_list([],[]). now matches. So it begins to unwind the recursion. It unifies _69734 with the empty list. It unifies _69116 with [3], and then _55684 with [2,3] and finally _52812 with [1,2,3] and it declares success. The program is true.

In a nutshell, it does this:

copy_list([1, 2, 3], _52812)
copy_list([2, 3], _55684)
copy_list([3], _69116)
copy_list([], _69734)
copy_list([], [])
copy_list([3], [3])
copy_list([2, 3], [2, 3])
copy_list([1, 2, 3], [1, 2, 3])
  • Related