在prolog

时间:2017-06-05 15:36:31

标签: recursion prolog

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

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

我一直收到错误:超出全局堆栈

2 个答案:

答案 0 :(得分: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时尝试运行)。交换子句顺序只隐藏了这个问题而且只是一些。但是,订单对于提高效率非常重要。

答案 1 :(得分:1)

切换条款的顺序。将第二个条款放在首位,否则它没有机会做出贡献(即停止),第一个条款继续倒数到负无穷大。

当然,更好的方法是通过添加一个简单的测试作为第一个条款的第一个目标,使两个条款相互排斥。