0

我对这个del/3谓词的查询如何工作有疑问:

/* BASE CASE: If I delete X from List and X is the HEAD of List, NewList is
              the Tail of List
*/
del(X, [X|Tail], Tail).

/* GENERAL CASE: If the head of List is not X then the program have to delete
                 X in the Tail of List
*/
del(X, [Y|Tail], [Y|Tail1]) :- del(X, Tail, Tail1).

谓词逻辑非常简单:从列表中删除 X 项创建一个没有 X 的新列表:如果 X 在列表的头部,则新列表是它的尾部。否则,如果 X 项不在列表的头部,尝试在 Tail 中找到它(并删除)创建一个新的尾部 Tail1。

好的,所以我对谓词逻辑没有问题,但我在尝试理解这个查询的工作方式时遇到了一些问题(我必须在另一个程序中使用它):

del([Top1|Stack1], [[a,b,c],[],[]], Stacks1).

所以这个查询必须从堆栈列表[[a,b,c],[],[]]中删除[Top1|Stack1](在这种特殊情况下,我有 3 个堆栈: [a,b,c]和 2 个空堆栈:[]) 生成一个名为Stacks1的新堆栈列表

如果我尝试执行查询的跟踪,我会得到:

[trace]  ?- del([Top1|Stack1], [[a,b,c],[],[]], Stacks1).
   Call: (7) del([_G389|_G390], [[a, b, c], [], []], _G412) ? creep
   Exit: (7) del([a, b, c], [[a, b, c], [], []], [[], []]) ? creep
Top1 = a,
Stack1 = [b, c],
Stacks1 = [[], []] .

我有一些难以理解的原因:[Top1|Stack1]与第一个堆栈[a, b, c]统一

编辑:我认为可能以这种方式工作:堆栈列表是:[[a,b,c],[],[]]这是一个列表列表,其中第一个列表是:[a,b,c ](即这个列表的头部**

因此,当我写:[Top1|Stack1]时,会发生:

Top1 = [a,b,c] * Stack1 = [[],[]] *

碰巧Top1堆栈列表中的第一个堆栈,Stack1是其他堆栈的列表。

所以当我写谓词时:

 del([Top1|Stack1], Stacks, Stacks1).

(例如:Stacks = [[a,b,c],[],[]]

它以这种方式工作:

它将 Top1 与堆栈列表中的第一个堆栈统一起来:[a,b,c]并将其从堆栈列表中删除...

当我执行一个简单的查询时,我的问题与 Prolog 语义有关:

del(b, [a,b,c], NewList).

它从列表中删除 b 项和 NewList=[a,c]

但是当我知道要删除的项目的字段类似于:[Head|Tail]是要删除的 Head 项目吗?

4

1 回答 1

3

查询从的元素中D=[[a,b,c],[],[]], del([A|B], D, C)选择任何匹配的列表。这里唯一的可能是,剩菜是。[A|B]D[A|B]=[a,b,c]C=[[],[]]

一般来说del完全回溯,一一找到所有的可能性。这里只有一种可能。

为了更好地理解del,试试这个:

2 ?- del(X,[A,B,C],D).
X = A,
D = [B, C] ;
X = B,
D = [A, C] ;
X = C,
D = [A, B] ;
false.

它不是试图“找到” X;它只是从可能性中一一挑选出来(第二个论点)。这就是谓词所说的 / 所做的。

当然,如果列表被实例化为基本术语,有些可能不匹配并且会被拒绝,从而产生正在搜索的值的印象:

4 ?- del(b, [a,b,c,d], R).
R = [a, c, d] ;
false.

5 ?- del(b, [a,b,X,d], R).
R = [a, X, d] ;
X = b,
R = [a, b, d] ;
false.

该术语[A|B]仅匹配任何非空列表(或逻辑变量):

6 ?- del([A|B], [[a],b,X,d], R).
A = a,
B = [],
R = [b, X, d] ;
X = [A|B],
R = [[a], b, d] ;
false.

7 ?- del([A|B], [[a],b,[],d], R).
A = a,
B = [],
R = [b, [], d] ;
false.

因此 egdel([A|B], [[1,2,3], [4,5], [], [6]], R)将从该示例调用的第二个参数中给出的 4 个列表中选择任何非空列表,并且在执行此操作时,它将绑定A到头元素和B被选择的列表的其余元素。

这个谓词在野外被称为select/3。:)


插图:

del(X, [X|Tail], Tail).

     X        X
     --------------------
              T        T
              a        a
              i        i
              l        l

del(X, [Y|Tail], [Y|Tail1]) :- del(X, Tail, Tail1).

              Y        Y
     --------------------
              T        T
       /      .        a
     X -      .        i
       \      .        l
              .        1
              l
于 2013-05-09T12:33:44.890 回答