2013-02-21 52 views
2

我無法理解下面的代碼。
有人可以解釋一步一步發生了什麼,如果我有後續輸入:遵循prolog代碼做什麼?

append([1,2,3], Lst). 

其實,我不;噸得到怎樣1,2附加列表LST結果。

append([_], []).  
append([H|T], [H|N]) :- append(T,N). 

回答

6

這聽起來像你是Prolog的新手。如果是這樣,歡迎!我們來分析一下。

這個不幸命名的函數有兩個子句。 Prolog查看這些條款以查看哪一個適用。當它找到一個匹配時,它會嘗試執行它。如果在執行某個操作時出現故障,它將備份並嘗試下一個選項。這些選擇點恰恰根據程序而變化;在這個程序中,唯一一個將在子句級別,決定使用哪個規則。

查看第一條規則的一種方法是,它說「一個包含一個元素的列表,不管該元素是什麼,都與空列表有關。」查看append([_], []),如果我們有X = [foo]Y = [],它會持有,因爲[foo]是一項清單,而[]是空白清單。這個規則是很好的Prolog風格,因爲它不管實例化都可以工作:我們可以提供左邊或右邊,也可以不提供,不重要。

第二個條款也很簡單。它說,如果左邊的參數和右邊的參數都以相同的項目開始,並且其餘的列表也是由相同的謂詞相關的,則左邊的參數和右邊的參數是相關的。換句話說,如果我有兩個列表XY這樣append(X, Y)爲真,那麼append([H|X], [H|Y])也是如此。不管H是什麼,X和Y都是無關緊要的,除非append/2暗示。

從邏輯上思考,如果我知道任何一個項目列表與空列表相關,並且任何列表都與以相同項目開頭並且相同的列表相關,則唯一可以列出的列表如此相關的是每個項目都是相同的列表,除了左側列表中最後有一個項目不在右側。所以[1,2,3,4]與[1,2,3]有關,但[1,2,3,foo]和[1,2,3]也是如此。

在程序上,讓我們來看看,因爲這謂語用此組參數處理會發生什麼:

append([1,2,3], X). 

的第一條規則不匹配[1,2,3]。因此,我們必須看看第二條規則:

append([1|[2,3]], [1|X]) :- append([2,3], X). 

我們可以重複:

append([2|[3]], [2|Y]) :- append([3], Y). 

現在的第一條規則確實比賽:

append([3], []). 

所以把他們放在一起:

append([1,2,3], [1|X]) implies 
    append([2,3], X=[2|Y]) implies 
    append([3], Y=[]) 
    so Y = [] 
so X = [2] 
so the right side is [1,2]. 

Prolog的跟蹤將顯示你基本上是相同的信息:

?- trace, append([1,2,3], X). 
    Call: (7) append([1, 2, 3], _G1633) ? creep 
    Call: (8) append([2, 3], _G1752) ? creep 
    Call: (9) append([3], _G1755) ? creep 
    Exit: (9) append([3], []) ? creep 
    Exit: (8) append([2, 3], [2]) ? creep 
    Exit: (7) append([1, 2, 3], [1, 2]) ? creep 

是什麼讓這個Prolog的代碼混淆的是,它並不像你告訴Prolog的如何做任何事情。事實並非如此,但通過指定邏輯上的真實性,Prolog能夠自己弄明白。這是非常聰明的代碼。如果這是Haskell,我們將討論內置函數init,它將返回除最後一項以外的所有列表。

希望這會有所幫助!

+0

謝謝。這是非常有幫助的。 – Chaos 2013-02-28 19:27:18