Prolog Nim Game - 超出本地堆栈错误

我最近一直在做一些Prolog。我读过Prolog的艺术书。他们在那里有一个Nim游戏实现。所以我把它重写为SWI-Prolog,除了本地堆栈错误之外,一切似乎都很好。 调试后我发现它似乎永远循环在程序的这一部分:
nim_sum([N|Ns],Bs,Sum):-
      binary(N,Ds), nim_add(Ds,Bs,Bs1), nim_sum(Ns,Bs1,Sum).
nim_sum([],Sum,Sum).

nim_add(Bs,[],Bs).
nim_add([],Bs,Bs).
nim_add([B|Bs],[C|Cs],[D|Ds]):-
    D is (B+C) mod 2, nim_add(Bs,Cs,Ds).
有没有人遇到过这种问题?对于某些替代实施的任何建议?     
已邀请:
为了避免“堆栈外”问题,通常需要以“最后调用优化”或“尾递归”形式编写递归谓词。 这里似乎应该颠倒nim_sum / 3的两个子句(首先放置“fact”子句,这是终止条件)。然后调用nim_sum / 3使自己在具有正文的子句中没有任何回溯点打开(假设二进制/ 2和nim_add / 3是确定性的)。 尝试将这两个子句交换为nim_sum,并告诉我们它是如何工作的。 补充:在进一步思考nim_add / 3后,我怀疑Prolog引擎可能无法检测到它是确定性的,即仅以一种方式成功。这是削减工作!运营商。最简单的解决方案是在nim_sum / 3调用自身的位置前面添加一个剪切,这样在递归调用时肯定没有打开回溯点。然而,这更像是Prolog的“精神”:
nim_sum([],Sum,Sum).  
nim_sum([N|Ns],Bs,Sum):-  
    binary(N,Ds),  
    nim_add(Ds,Bs,Bs1),  
    nim_sum(Ns,Bs1,Sum).  

nim_add(Bs,[],Bs) :- !.  
nim_add([],Bs,Bs) :- !.  
nim_add([B|Bs],[C|Cs],[D|Ds]):-  
    D is (B+C) mod 2,  
    nim_add(Bs,Cs,Ds).  
同样,这假设二进制/ 2是确定性的,可能是将整数(非负?)转换为0和1的列表,首先是最低有效位。     

要回复问题请先登录注册