簡體   English   中英

Prolog中的差異列表和可變變量

[英]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/3read_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM