我试图在Prolog shiftL(L1,N,L2)
中建立关系,将L1
向左移动N
次(旋转),结果为L2
,所以例如shiftL([1,2,3], 2, [3,1,2])
是真的。
我尝试了以下内容:
shiftL([],N,[]).
shiftL([X|Xs],1,L) :- append(Xs,[X],L).
shiftL([X|Xs],N,L) :- N1 is N-1 , N=\=1 , shiftL(L1,N1,L) , append(Xs,[X],L1).
它的效果很好,但是在给我结果之后它总是继续做其他事情并且我得到了堆栈溢出:
?- shiftL([1,2,3], 2, L).
L = [3, 1, 2] ;
ERROR: Out of global stack
我不知道造成这种情况的原因。我以为我用第二行和N=\=1
语句覆盖了基本情况。
提前感谢您的帮助!
答案 0 :(得分:2)
以下是相关的程序片段(failure-slice):
shiftL([],N,[]) :- false. shiftL([X|Xs],1,L) :- append(Xs,[X],L), false. shiftL([X|Xs],N,L) :- N1 is N-1 , N=\=1, shiftL(L1,N1,L), false,append(Xs,[X],L1).
基本上,目标append(Xs,[X],L)
循环。它循环,因为Xs
和L
都不是列表 - 这是一个固定长度的列表。要看到这一点,请考虑递归目标
shiftL(L1,N1,L)
。正如您在片段中看到的那样,L1
无处可寻。因此它是一个未实例化的变量。 L
是查询中的变量。因此,您需要将L1
或L
列入清单。就像把隐藏的append(Xs,[X],L1)
放在前面一样。
还有另一个循环:
?- shiftL([1,2,3],-1,L).
我相信你可以自己解决这个问题。
有关故障切片如何缩小非终止问题的更多示例,请参阅failure-slice。