我認爲你有這樣的想法,Prolog解釋器將差異列表視爲特殊的東西。情況並非如此:Prolog沒有意識到差異列表的概念(幾乎除了某些語法糖之外的幾乎所有概念)。他只看到:
L=-(|(a, |(b, |(c, |(d, |(e, []))))), |(d, |(e, [])))
其中-/2
和|/2
是仿函數,並a
,b
,c
,d
,e
和[]
是常數。
差異列表是一個簡單的編程技術(例如像動態規劃是一種技術,以及時,編譯器無法檢測,也不區別對待動態編程程序)。它用於高效地將表達式中的(部分)非統一部分統一起來。
說要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/3
在O(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
。
閱讀該部分的關鍵是*代表*。如果你看一下這本書,那麼當這些例子可以與最高級別的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是任何列表。'所以它不是一個例子以最高級別運行,但代表*表示*您應該考慮的內容,因此在將其用作頂級輸入時出現錯誤。 –
'L'不能都是'[a,b,c | [d,e]] - [d,e]'和'[a,b,c]'。這是兩種不同的結構。 – lurker
@lurker我現在看到了,但正如在評論中澄清的那樣,可能是爲什麼我沒有看到差異列表的實際好處。如果你想使用連接列表,你總是需要Willem Van Onsem建議的* finalize *步驟。 –