2017-01-11 66 views
1

當我寫下this question on an empty list as a difference list我想考什麼,我知道那些結構。但是,當我嘗試一些比較不同符號的簡單事情時,似乎我錯了,並且我確實知道實際上差異列表正在發生什麼。如何使用差異表的Prolog的解釋

?- L = [a,b,c|[d,e]]-[d,e], L = [a,b,c]. 
false % expected true 

我在SWI-Prolog和SICStus上測試了這個。我驗證了這個符號,因爲它是如何寫在Bratko的人工智能Prolog編程中,第210頁,但顯然統一是不可能的。這是爲什麼?這些符號不具有相同的聲明意義嗎?

+2

閱讀該部分的關鍵是*代表*。如果你看一下這本書,那麼當這些例子可以與最高級別的AKA解釋器一起使用時,它們的前綴是「?-'。例如,[a,b,c] - []或[a,b,c,d,e] - [d, e]或[a,b,c,d,e | T] - [d,e | T]或[a,b,c | T] -T其中T是任何列表。'所以它不是一個例子以最高級別運行,但代表*表示*您應該考慮的內容,因此在將其用作頂級輸入時出現錯誤。 –

+1

'L'不能都是'[a,b,c | [d,e]] - [d,e]'和'[a,b,c]'。這是兩種不同的結構。 – lurker

+0

@lurker我現在看到了,但正如在評論中澄清的那樣,可能是爲什麼我沒有看到差異列表的實際好處。如果你想使用連接列表,你總是需要Willem Van Onsem建議的* finalize *步驟。 –

回答

3

我認爲你有這樣的想法,Prolog解釋器將差異列表視爲特殊的東西。情況並非如此:Prolog沒有意識到差異列表的概念(幾乎除了某些語法糖之外的幾乎所有概念)。他只看到:

L=-(|(a, |(b, |(c, |(d, |(e, []))))), |(d, |(e, []))) 

其中-/2|/2是仿函數,並abcde[]是常數。

差異列表是一個簡單的編程技術(例如像動態規劃是一種技術,以及時,編譯器無法檢測,也不區別對待動態編程程序)。它用於高效地將表達式中的(部分)非統一部分統一起來。

說要append/3兩個列表。你可以這樣做如下:

%append(A,B,C). 
append([],L,L). 
append([H|T],L,[H|B]) :- 
    append(T,L,B). 

但這運行在O(n)的:您首先需要通過整個第一個列表進行迭代。如果該列表包含數千個元素,則需要很長時間。

現在,您可以定義自己合同,你會養活append_diff/3不僅列表中,但一個元組-(List,Tail)其中List是到列表的開始時的參考,並Tail是的末尾引用沒有統一的名單。符合此要求的結構示例爲Tail-Tail,[a|Tail]-Tail,[1,4,2,5|Tail]-Tail

現在可以有效append_diff/3O(1)有:

append_diff(H1-T1,T1-T2,H1-T2). 

爲什麼?因爲你統一第一個列表的非統一的尾巴與第二個列表。現在第二個列表的非統一尾部成爲最終列表的尾部。因此,採取例如:

append_diff([a|T1]-T1,[1,4,2,5|T2]-T2,L). 

如果調用謂詞,正如你看到的上面,T1將與[1,4,2,5|T2]統一,所以現在第一個列表摺疊到[a|[1,4,2,5|T2]]或更短[a,1,4,2,5|T2],因爲我們也有一個參考T2,我們可以「返回」(在Prolog中沒有任何內容是返回),[a,1,4,2,5|T2]-T2:帶有開尾的新差異列表T2。但是,這僅僅是因爲你給-特殊的含義自己:爲序言-簡直是-,它不是減去,它不計算差值等Prolog的不不重視語義函子。如果你會使用+而不是-,那就不會有絲毫的區別。

所以要回到你的問題:你只需向Prolog說明L = -([a,b,c,d,e],[d,e])和後來的狀態即L = [a,b,c]。現在很明顯,這兩種表達方式是不能統一的。所以Prolog說false

+0

我現在明白他們爲什麼不統一,但我不明白append_diff/3在實踐中會很有用。我的意思是,如果這就是你如何添加,結果將是'[a,1,4,2,5 | T2] -T2'。你仍然沒有你想要的價值,即'[a,1,4,2,5]',對吧? –

+0

@BramVanroy:好吧,你可以定義一個謂詞'finalize(A - [],A)。「,它可以」完成「diff列表。如果你接着調用'finalize([a,1,4,2,5 | T2] -T2,Result)。''Result'將會是'[a,1,4,2,5]'。但正如前面所說,你自己如何解釋數據是一回事。你可以將'[a,1,4,2,5 | T2] -T2'解釋爲與[[a,1,4,2,5]'相當的列表*等價*。 –

+0

但是Prolog並沒有像這樣解釋結構,所以'finalize/2'步驟需要有一個可用的連接列表,對嗎? (關於其他問題發佈的評論如下)作爲示例,我們要追加[a,b]和[c,d]。建議的解決方案:'conc_d([a,b | T] -T,[d,e | T1] -T1,L).'但是,結果是'L = [a,b,c,d | T1] -T1',但作爲程序員,我需要'[a,b,c,d]',簡單明瞭。我有一種感覺我錯過了這一觀點,但我沒有看到實際的好處,也沒有看到如何在實踐中使用差異列表。 –