Reputation: 21
This is the program I have:
foo(L,[H|R1]) :-
foo(L,R1,H).
foo([H],[],H).
foo([H|T],[H|T1],R) :-
foo(T,T1,R).
This is the query:
foo([1,2,3,4,5,6],X).
I don't understand what this program does, can someone help me and explain how does it work?
Upvotes: 2
Views: 126
Reputation: 10120
In Prolog, there is no need to understand the source code. Instead, let Prolog do this for you. Just ask the most general query:
?- foo(L,R).
L = [_A],
R = [_A]
; L = [_A,_B],
R = [_B,_A]
; L = [_A,_B,_C],
R = [_C,_A,_B]
; L = [_A,_B,_C,_D],
R = [_D,_A,_B,_C]
; L = [_A,_B,_C,_D,_E],
R = [_E,_A,_B,_C,_D]
; L = [_A,_B,_C,_D,_E,_F],
R = [_F,_A,_B,_C,_D,_E]
; L = [_A,_B,_C,_D,_E,_F,_G],
R = [_G,_A,_B,_C,_D,_E,_F]
; L = [_A,_B,_C,_D,_E,_F,_G,_H],
R = [_H,_A,_B,_C,_D,_E,_F,_G]
; ... .
Do you see a pattern here?
Upvotes: 2
Reputation: 71074
To understand it easier, put the recursive clause above the base one:
foo( [H | T], [H | T1], R) :- foo( /* T = [_|_] */
T, T1, R).
foo( [R], [], R).
So we advance along the two lists (that hold the same elements, H
) until we hit the last element in the first list ([R]
), at which point the second list is exhausted ([]
), and we get hold of that last element (R
).
This means that foo( A, B, R) :- append( B, [R], A).
. Thus,
foo( L, [E | R1]) :- % foo( L, R1, E).
append( R1, [E], L). % R1 ++ [E] = L
i.e. foo( L, M)
relates two lists L
, M
, where L
is M
with its first element E
"flipped" to the list's end:
L : .............E
M : E.............
% ---- R1 -----
Upvotes: 0
Reputation:
You could try to refactor it. If I start with:
foo(L, [H|R1]) :-
foo(L, R1, H).
foo([H], [], H).
foo([H|T], [H|T1], R) :-
foo(T, T1, R).
I can change the argument order foo(1,2,3) to foo(2,3,1):
foo(L,[H|R1]) :-
foo(R1, H, L).
foo([], H, [H]).
foo([H|T1], R, [H|T]) :-
foo(T1, R, T).
Now I can change the 2-nd argument of foo, and pass [H] instead of H:
foo(L, [H|R1]) :-
foo(R1, [H], L).
foo([], H, H).
foo([H|T1], R, [H|T]) :-
foo(T1, R, T).
Now you can rename the predicates to roll and append:
roll(L, [H|R1]) :-
append(R1, [H], L).
append([], H, H).
append([H|T1], R, [H|T]) :-
append(T1, R, T).
Upvotes: 2