我似乎无法完全理解prolog (gprolog)的一些行为。作为背景,旋转应该比较两个列表,并查看它们是否已被移动(如下所示)。
?- rotate(1,[4,1,2,3],[1,2,3,4]). 应该还真。然而,当提出上述问题时,prolog似乎并不尊重规则的顺序。
rotate(0,[],[],[]).
%base case
rotate(0,[],[H|T1],[H|T2]):- rotate(0,[],T1,T2).
%recurse over the remainder list (the first list from S to the end)时,Prolog将忽略下面的谓词
rotate(S,[H|T1],[H|T2],L):-S=:=0,rotate(0,T1,T2,L).
%recurse over the elements from S to the end of list1从另一个谓词(直接在下面)进行回溯。
rotate(S,[H|T1],L,T2):-S > 0,S1 is S - 1,rotate(S1,T1,L,[H|T2]).
%add elements 1 to S into the remainder list
rotate(S,L1,L2):-len(L1,Len),S1 is S mod Len,!,rotate(S1,L1,L2,[]).
%ensure the shift is not out of bounds, call rotate/4
%utility function because couldn't use length
len([],Ret,Ret).
len([_|T],Len,Ret):-Len1 is Len+1,len(T,Len1,Ret).
len(L,Len):-len(L,0,Len).我通过跟踪发现了这种行为,坦率地说,我很困惑为什么它不会回溯并命中下一个谓词,而是失败并返回false。
我也对更好的方法持开放态度,因为这是期中考试的练习。
发布于 2017-10-26 04:39:50
对不起,你的主要问题我没有答案。跟踪执行以确定回溯行为是调试Prolog时的一种“最后机会”,您最好信任引擎--也因为它发生,调试器有时会出错:)
当一个谓词有N个替代项时,您可以在测试后立即对第一个N1子句进行裁剪,然后(最终)在最后一个子句中避免测试。
目的是明确的:将执行提交到成功的路径。相反,您做了相反的操作,将裁剪放在了最后一个循环/4子句中,在这里它是无用的。因此,这不应该是罪魁祸首,只是一个细微差别,表明您还没有Prolog编程模型。
我还建议避免“早期优化”您的作业:当逻辑正确时,程序应该独立工作,而S大于列表长度。相反,也许你应该考虑一下,如果给出一个负S作为论证,会发生什么。
如果您以“声明式”调试,则您的谓词似乎无法工作:
?- rotate(2,[4,1,2,3],R).
R = [2, 3, 1, 4] ;
false相反,我希望[2, 3, 4, 1],也就是这个简单定义的结果
rotate(N, L, R) :- N > 0, N1 is N-1, rotate(L, T), rotate(N1, T, R).
rotate(0, L, L).
rotate([X|Xs],R) :- append([Xs,[X]],R).旋转/2使用方便的追加/2助手,以“发送回”头部。我相信你不会有问题用附件/3或你自己的定义.
https://stackoverflow.com/questions/46944639
复制相似问题