Recursion Prolog-flatte/2实现
下面是我的Recursion Prolog-flatte/2实现,recursion,prolog,infinite-recursion,Recursion,Prolog,Infinite Recursion,下面是我的展平/2实现: flt([], []). flt([H|L], [H|X]):- not(is_list(H)), flt(L, X). flt([H|L], X):- append(R, F, X), flt(H, R), flt(L, F). 预期结果如下: ?- flt([1,[2,3,[4,5],6],7], X). X = [1, 2, 3, 4, 5, 6, 7] 然而,当我点击超出堆栈限制。为什么会发生这种情况?无限递归在哪里?
展平/2
实现:
flt([], []).
flt([H|L], [H|X]):-
not(is_list(H)),
flt(L, X).
flt([H|L], X):-
append(R, F, X),
flt(H, R),
flt(L, F).
预期结果如下:
?- flt([1,[2,3,[4,5],6],7], X).
X = [1, 2, 3, 4, 5, 6, 7]
然而,当我点击代码>超出堆栈限制。为什么会发生这种情况?无限递归在哪里?
谢谢。问题是您只使用未实例化的变量调用append(R,F,X)
对于flt(+List,-Flatlist)
,只有一种解决方案。然而,在回溯时,append(R,F,X)
会一次又一次地尝试,但从未找到其他解决方案
您可以通过询问来测试这一点
?- append(R, F, X).
R = [],
F = X ;
R = [_948],
X = [_948|F] ;
R = [_948, _960],
X = [_948, _960|F] ;
R = [_948, _960, _972],
X = [_948, _960, _972|F] ;
R = [_948, _960, _972, _984],
X = [_948, _960, _972, _984|F] ;
R = [_948, _960, _972, _984, _996],
X = [_948, _960, _972, _984, _996|F]
...
解决方案是重新安排第三条中的目标:
flt([H|L], X):-
flt(H, R),
flt(L, F),
append(R, F, X).
这是一个很好的例子,说明Prolog不是纯粹的声明性的,因为它通过简单的时间顺序回溯实现解析,将过程特性强加于语言
为了说明这个问题,请看一下这个跟踪(为了强调循环问题,我跳过了很多次):
这张图用图形显示了它。询问其他答案后发生的情况为红色
另一种可能的解决方案是增加切割:
flt([], []).
flt([H|L], [H|X]):-
not(is_list(H)),
flt(L, X),
!.
flt([H|L], X):-
append(R, F, X),
flt(H, R),
!,
flt(L, F).
flt([], []).
flt([H|L], [H|X]):-
not(is_list(H)),
flt(L, X),
!.
flt([H|L], X):-
append(R, F, X),
flt(H, R),
!,
flt(L, F).