2017-03-21 15 views
0

本地棧我在swipl序言 - 出錯:在Linux

edge(X,Y) :- edge(X,Z),edge(Z,Y). 
edge(a,b). 
edge(a,f). 
edge(b,c). 
edge(c,d). 
edge(g,c). 
edge(f,g). 
edge(f,c). 
edge(f,e). 
edge(c,e). 
edge(e,d). 

有一個非常簡單的程序,但是當Ι進行查詢edge(a,c).Ι得到一個走出本地堆棧異常。奇怪的是,當我在窗口中執行相同的查詢時,該程序完美地工作。

我試圖增加本地堆棧,但只是程序需要更長的時間來拋出異常。

+2

在Windows上,這也應該失敗,因爲你創建無限遞歸... –

回答

2

你的謂詞定義了一個可愛的無限循環。它只是坐在那裏,並自稱自己,甚至從來沒有嘗試事實,因爲謂詞是第一個,並被命名爲事實相同。 (1)在謂詞之前斷言事實,(2)不用與事實同名的謂詞來定義謂詞(從技術上講,它並不意味着同一事物,所以爲什麼要這樣做) (3)在遞歸子句中,在遞歸調用之前檢查一個預先定義的邊。

edge(a,b). 
edge(a,f). 
edge(b,c). 
edge(c,d). 
edge(g,c). 
edge(f,g). 
edge(f,c). 
edge(f,e). 
edge(c,e). 
edge(e,d). 

connected(X, Y) :- 
    edge(X, Y). 
connected(X, Y) :- 
    edge(X, Z), connected(Z, Y). 
+0

謝謝,它的工作原理。但是你知道爲什麼Windows不會崩潰嗎? –

+0

@GeovanyGameros你能解釋一下你的意思是「windows」不是「崩潰」嗎?你是說當你在Windows中運行你的代碼時,你沒有得到堆棧溢出?如果你不這樣做,究竟發生了什麼?這裏的問題是代碼進入無限遞歸。在Windows中,它可能會在看到堆棧溢出並報告它之前導致其他一些錯誤情況。 – lurker

+0

我的意思是在Windows中代碼沒有得到堆棧溢出。當我運行我的代碼時,我得到「真實」。可能我有另一個swi-prolog版本 –

2

觀察究竟是考慮的問題如下

 
edge(X,Y) :- edge(X,Z), false, edge(Z,Y). 
edge(a,b) :- false. 
edge(a,f) :- false. 
edge(b,c) :- false. 
edge(c,d) :- false. 
edge(g,c) :- false. 
edge(f,g) :- false. 
edge(f,c) :- false. 
edge(f,e) :- false. 
edge(c,e) :- false. 
edge(e,d) :- false. 

如果你的程序的這一片段並不終止,然後還你原來的計劃不會終止。看看還剩下什麼!單個遞歸,其中參數被忽略(Y)或傳遞(X)。因此,這個程序無法終止。換句話說:你的程序永遠不會終止。