这是我拥有的程序:
foo(L,[H|R1]) :-
foo(L,R1,H).
foo([H],[],H).
foo([H|T],[H|T1],R) :-
foo(T,T1,R).
这是查询:
foo([1,2,3,4,5,6],X).
我不了解该程序的功能,有人可以帮我解释一下它的工作原理吗?
答案 0 :(得分:2)
在Prolog中,无需了解源代码。而是让Prolog为您执行此操作。只需问最普遍的查询:
| ?- 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]
; ...
您在这里看到图案吗?
答案 1 :(得分:2)
您可以尝试对其进行重构。如果我以:
开头foo(L, [H|R1]) :-
foo(L, R1, H).
foo([H], [], H).
foo([H|T], [H|T1], R) :-
foo(T, T1, R).
我可以将参数顺序foo(1,2,3)更改为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).
现在我可以更改foo的第二个参数,并传递[H]而不是H:
foo(L, [H|R1]) :-
foo(R1, [H], L).
foo([], H, H).
foo([H|T1], R, [H|T]) :-
foo(T1, R, T).
现在,您可以重命名谓词以进行滚动和追加:
roll(L, [H|R1]) :-
append(R1, [H], L).
append([], H, H).
append([H|T1], R, [H|T]) :-
append(T1, R, T).
答案 2 :(得分:0)
为便于理解,请将递归子句放在基数之上:
foo( [H | T], [H | T1], R) :- foo( /* T = [_|_] */
T, T1, R).
foo( [R], [], R).
因此,我们沿着两个列表(包含相同元素,H
)前进,直到命中第一个列表([R]
)中的最后一个元素,此时第二个列表被耗尽( []
),我们掌握了最后一个元素(R
)。
这意味着foo( A, B, R) :- append( B, [R], A).
。因此,
foo( L, [E | R1]) :- % foo( L, R1, E).
append( R1, [E], L). % R1 ++ [E] = L
即foo( L, M)
关联两个列表L
,M
,其中L
是M
,其第一个元素E
“翻转”到列表的末尾:< / p>
L : .............E
M : E.............
% ---- R1 -----