知識庫遞歸另外在Prolog中
add(0,Y,Y). // clause 1
add(succ(X),Y,succ(Z)) :- add(X,Y,Z). // clause 2
查詢
add(succ(succ(succ(0))), succ(succ(0)), R)
痕量
Call: (6) add(succ(succ(succ(0))), succ(succ(0)), R)
Call: (7) add(succ(succ(0)), succ(succ(0)), _G648)
Call: (8) add(succ(0), succ(succ(0)), _G650)
Call: (9) add(0, succ(succ(0)), _G652)
Exit: (9) add(0, succ(succ(0)), succ(succ(0)))
Exit: (8) add(succ(0), succ(succ(0)), succ(succ(succ(0))))
Exit: (7) add(succ(succ(0)), succ(succ(0)), succ(succ(succ(succ(0)))))
Exit: (6) add(succ(succ(succ(0))), succ(succ(0)), succ(succ(succ(succ(succ(0))))))
我的問題
- 我看到如何在第遞歸調用2條的最外SUCC() 在每個呼叫對參數1.
- 我看看它是如何在增加了一個外SUCC()以3參數每次通話。
- 我看到當第一個參數作爲這些遞歸調用 的結果達到0.此時,我看到1st子句如何將第二個參數 複製到第三個參數。
這是我困惑的地方。
一旦執行第1條款,並在第2條自動 得到執行爲好,然後加入SUCC()第一個參數?
另外,程序如何終止,爲什麼它不會僅僅保持 無限地爲第一個和第三個參數添加succ()?
從LearnPrologNow.com解釋(我不知道)
讓我們通過使用方式的Prolog來處理這個查詢走一步看一步。下面給出了查詢的跟蹤和搜索樹的 。
第一個參數不是0,這意味着只能使用add/3的第二個子句 。這導致遞歸調用add/3。將 最外面的succ函數從原始查詢 的第一個參數中刪除,結果將成爲遞歸查詢的第一個參數。第二個參數不變地傳遞給 遞歸查詢,遞歸查詢的第三個參數是一個 變量,下面給出的跟蹤中的內部變量_G648。注意 _G648尚未實例化。但是它與R (我們用作原始 查詢中的第三個參數的變量)共享值,因爲當查詢是 與第二個子句的頭部統一時,R被實例化爲succ(_G648)。但這意味着R是 不再是一個完全沒有實際意義的變量。現在它是一個複雜的 術語,它有一個(未被證實的)變量作爲它的參數。
接下來的兩個步驟基本相同。隨着每一步的第一個參數變成一個succ小一層;下面給出的跟蹤和 搜索樹都很好地顯示了這一點。與此同時,在每一步都會向R添加一個仿函數,但始終將最內層的變量 變爲無實際意義。在第一次遞歸調用R之後是 succ(_G648)。在第二次遞歸調用之後,_G648被succ(_G650)實例化爲 ,所以R是succ(succ(_G650)。在第三次遞歸調用之後,_G650被succ(_G652)實例化並且因此 變爲succ(succ (SUCC(_G652)))。搜索樹顯示這一步 一步實例。
在這個階段,所有SUCC函子已經被扒掉第一 參數,我們可以應用基本條款。第三個參數是 等同於第二個參數,因此複數項R中的'hole'(未示例的 變量)最終被填充,並且我們通過。
感謝您花時間回答我的問題,並提供比本書更好的解釋。 – prolog
非常歡迎您!正如我所看到的那樣,Prolog的一個主要吸引力是我們*不必*以這種痛苦的方式來調試我們的程序。相反,我們可以基於程序的聲明性屬性應用更強大的調試方法,並通過應用邏輯推理非常快速地縮小代碼中的錯誤。跟蹤只會導致您遠離語言的真正威力和普遍性,迫使您在特定的使用方向上閱讀您的代碼。請參閱我的個人資料頁面,瞭解我希望能幫助您學習Prolog的資源。請享用! – mat
也許我最大的問題之一來自純粹的程序編程背景。我看到了您的個人資料中的鏈接,我想知道爲什麼他們在Google中的排名不如LearnPrologNow:D – prolog