2017-06-05 55 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。交換子句順序只隱藏了這個問題,只是有所不同。然而,訂單對提高效率很重要。