2017-06-05 36 views
3

我试图生成一个从N到1的数字列表,而不使用任何内置谓词,如findall或numlist。我究竟做错了什么 ?生成prolog编号从1到1的列表

pred(N,[H|T]):- H is N, N1 is N-1, pred(N1,T). 
    pred(1,[]). 

我不断收到出错:全球栈

+0

您不需要'H是N'('is/2'用于算术表达式计算 - 请参阅文档)。你可以把'pred(N,[N | T]): - N1是N-1,pred(N1,T)。“但有些东西不见了......你有什么条件可以假设这里是关于'N'的吗?对于这个条款它可以有任何价值吗?你需要一个条件来避免无限递归... – lurker

+0

你的基本情况也是错误的。数字从1到1的列表真的是空列表,'[]'? – lurker

+0

我切换了子句的顺序,并删除了H是N,也在pred(1,[])中将0切换为0。谢谢 ! – Akimm231

回答

1

开关的条款的顺序。把第二个句子放在第一位,否则它没有机会做出贡献(即停止),第一个小句继续倒数到负无穷大。

当然更好的办法是通过添加一个简单的测试作为第一个子句的第一个目标来使两个子句相互排斥。

+0

谢谢!有效 。 – Akimm231

2

最完整的解决方案是:

pred(1, [1]). 
pred(N, [N|T]) :- 
    N > 1, 
    N1 is N-1, 
    pred(N1, T). 

没有N > 1条件,你仍然可以得到一个堆栈溢出:

| ?- pred(3, L). 

L = [3,2,1] ? ; 

Fatal Error: global stack overflow (size: 32768 Kb, reached: 32765 Kb, environment variable used: GLOBALSZ) 

但随着N > 1条件:

| ?- pred(3, L). 

L = [3,2,1] ? ; 

(1 ms) no 
| ?- 

此外,使用正确的条件,谓词的顺序不再重要。这是因为您的条款恰当地只在他们应该达到的条件下运作。没有它,你的pred(N, [N|T]) :- ...条款,这只是打算在N > 1也会试图运行时运行N =< 1。交换子句顺序只隐藏了这个问题,只是有所不同。然而,订单对提高效率很重要。