[英]Difference lists in Prolog and mutable variables
差異列表是否能夠“解決”變量在prolog中不可變的事實?
即如果我使用差異列表實現追加:
diff_append(OpenList, Hole, L2) :-
Hole = L2.
然后運行:
X=[a,b,c|Hole], diff_append(X, Hole, [d,e,f]).
在某種程度上,X已被用作可變變量。 為了我們的意圖和目的它已被改變?
換句話說,我們已經能夠修改X(可變)而不必構建新列表,比如說Z(不可變),這使得差異列表具有吸引力。 那么為什么不只是有可變變量呢?
更新:
diff_append2(OpenList-Hole,L2):-
Hole=L2.
X=[a,b,c|Ho]-Ho,diff_append2(X,[d,e,f]).
差異列表用於解決另一個限制:您需要遍歷整個列表以“追加”到它的結尾(想想一個單鏈表,其中有一個指向第一個元素的指針,但不是指向哨兵)。
在代碼中:因為列表[a, b, c]
是(傳統上)嵌套的術語.(a, .(b, .(c, [])))
,在它的末尾添加一個d
意味着“剝離” “在使用.(d, [])
替換末尾(中心)的[]
之前的每個術語。 所以,要實現append/3
:
append([], L, L).
append([H|T], L, [H|R]) :-
append(T, L, R).
這是傳統實施的方式 。
這個答案沒有涉及的內容是庫假設“返回”列表可能提供謂詞的差異列表版本,出於效率原因,以防您可能想要追加到列表的末尾。 示例可以是read_pending_codes/3
和read_pending_chars/3
,或者是findall/4
的四參數版本。
DCG是一種使用差異列表的便捷方式,無需顯式傳遞列表和尾部的兩個參數。
隊列的三個最基本的操作:制作一個空隊列,向后推,然后從前面彈出:
%% empty_queue(-Queue)
% make an empty queue
empty_queue(queue(0, Q, Q)).
%% queue_head(?Queue, ?Head, ?Queue0)
% Queue, with Head removed, is Queue0
queue_head(queue(s(X), [H|Q], Q0), H, queue(X, Q, Q0)).
%% queue_last(+Queue0, +Last, -Queue)
% Queue0, with Last at its back, is Queue
queue_last(queue(X, Q, [L|Q0]), L, queue(s(X), Q, Q0)).
正如人們應該注意的那樣, queue_head/3
將允許您從前面彈出或推送到隊列的前面。 queue_last/3
只允許你向后推:一旦你推了一個元素,你就沒有(常量時間)訪問隊列中的元素。
queue/3
術語的第一個參數是為了防止Richard O'Keefe所謂的“幻覺”變量,即從隊列中彈出比推送到它的元素更多的元素。 有趣的是,從上面的謂詞中省略第一個參數,看看會發生什么:
?- empty_queue(Q0), queue_head(Q0, H, Q1).
Q0 = queue([H|_G341], [H|_G341]),
Q1 = queue(_G341, [H|_G341]).
而不是失敗。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.