我無法理解下面的代碼。
有人可以解釋一步一步發生了什麼,如果我有後續輸入:遵循prolog代碼做什麼?
append([1,2,3], Lst).
其實,我不;噸得到怎樣1,2附加列表LST結果。
append([_], []).
append([H|T], [H|N]) :- append(T,N).
我無法理解下面的代碼。
有人可以解釋一步一步發生了什麼,如果我有後續輸入:遵循prolog代碼做什麼?
append([1,2,3], Lst).
其實,我不;噸得到怎樣1,2附加列表LST結果。
append([_], []).
append([H|T], [H|N]) :- append(T,N).
這聽起來像你是Prolog的新手。如果是這樣,歡迎!我們來分析一下。
這個不幸命名的函數有兩個子句。 Prolog查看這些條款以查看哪一個適用。當它找到一個匹配時,它會嘗試執行它。如果在執行某個操作時出現故障,它將備份並嘗試下一個選項。這些選擇點恰恰根據程序而變化;在這個程序中,唯一一個將在子句級別,決定使用哪個規則。
查看第一條規則的一種方法是,它說「一個包含一個元素的列表,不管該元素是什麼,都與空列表有關。」查看append([_], [])
,如果我們有X = [foo]
和Y = []
,它會持有,因爲[foo]
是一項清單,而[]
是空白清單。這個規則是很好的Prolog風格,因爲它不管實例化都可以工作:我們可以提供左邊或右邊,也可以不提供,不重要。
第二個條款也很簡單。它說,如果左邊的參數和右邊的參數都以相同的項目開始,並且其餘的列表也是由相同的謂詞相關的,則左邊的參數和右邊的參數是相關的。換句話說,如果我有兩個列表X
和Y
這樣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
,它將返回除最後一項以外的所有列表。
希望這會有所幫助!
謝謝。這是非常有幫助的。 – Chaos 2013-02-28 19:27:18