2012-02-10 24 views
4

我在序言很生疏,但我不知道爲什麼這樣的事情會失敗:序言:錯誤出全球棧的看上去像是一個級別的遞歸我

frack(3). 

frack(X) :- frack(X-1). 

所以,如果我評價弗蘭克•(4)。從定義的上述事實的互動提示下,我期望它不應該無休止地遞歸,因爲4-1 = 3。但我得到這個錯誤在SWI-Prolog的:

ERROR: Out of global stack 

回答

5

試試:

?- 4-1 = 3. 
false. 

爲什麼?因爲4-1 = -(4, 1),這顯然不是一個數字,而是一個複合詞。

推理有關的Prolog整數,使用約束,例如(使用GNU  的Prolog或B-的Prolog):

 
| ?- 4-1 #= X. 

X = 3 

在SWI-Prolog中,給你看圖形示蹤劑可能是有用發生的事情:

?- gtrace, frack(4). 

對於更復雜的調試,我建議如圖false's answer

+2

我不知道SWI有。太好了! – 2012-02-10 14:40:45

2

序言不會做算術除非您使用IS操作:

frack(X) :- X1 is X-1, frack(X1). 
3
frack(X) :- frack(X-1). 

應該

frack(X) :- Y is X - 1, frack(Y). 

你寫它的方式,X-1表達第一級統一X變量在下一級別,永遠不會爲frack(3)事實。

+0

感謝您使用「統一」一詞。現在它再次合理。我上次在1989年做過序言。這已經有一段時間了。 – 2012-02-10 14:39:46

+0

@WarrenP哇,所以你比我老一輩!我最後在1996年做了Prolog :) :) – dasblinkenlight 2012-02-10 14:44:27

+0

您的解決方案仍然沒有終止。 – false 2012-11-15 12:05:53

5

這是未終止的原因。您的查詢將不會終止,因爲你的程序的不終止:

 
?- frack(4). 

frack(3) :- false. 
frack(X) :- 
    frack(X-1), false. 

只能在可見部分修改的東西解決這個問題。三個SO答案建議使用(is)/2。但是這不會消除非終止!事實上,使用(is)/2導致基本相同片段:

 
?- frack(4). 

frack(3) :- false. 
frack(X) :- 
    Y is X - 1, 
    frack(Y), false. 

至少,現在frack(4)成功,但它會在回溯循環。您必須在可見部分更改某些內容,例如X的一些測試,以避免不終止。有關更多信息,請參見