这是教授讲座中的一个例子:
append([ ], A, A).
append([A|B], C, [A|D]) :- append(B,C,D).
Build a list:
?- append([a],[b],Y).
Y = [ a,b ]
Break a list into constituent parts:
?- append(X,[b],[a,b]).
X = [ a ]
?- append([a],Y,[a,b]).
Y = [ b ]
我花了3个小时试图抓住它而不能。本幻灯片之前的任何prolog概念都没有任何问题。没有提供进一步的解释,没有其他信息。这是所有的了。如果有人可以告诉我这个程序是如何运作的,我会爱他们直到死亡让我们分开。
答案 0 :(得分:2)
首先要了解的是:-
运算符。
this_will_be_true :- if_this_is_true
基本上,:-
右边的任何内容都是先决条件。一个很好的例子是:
sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).
这基本上意味着如果存在父Z,则X和Y是兄弟,这样Z就是X和Y的父。
append([ ], A, A).
这一行基本上意味着将某些内容附加到空列表中会返回该内容。这是递归的基本情况。
append([A|B], C, [A|D]) :- append(B,C,D).
此行表示将C附加到包含A和B的现有列表会返回一个包含A和D的列表,因为将C附加到B将返回D.
Build a list:
?- append([a],[b],Y).
Y = [ a,b ]
所以,这里发生的是Prolog返回Y
的唯一可能值,它满足给定两个初始值的两个规则。让我们考虑一下这是如何发生的。这需要首先通过第二条规则进行评估。因此[A|B]
为[a]
而C
为[b]
。
因此,对于[A|B]
,我们必须返回第一条规则,因为B
是空列表(它是[ ]
)。第一条规则基本上表明我们可以将[a]
写为[a|[ ]]
,它们是相同的。所以现在我们可以回到第二条规则。 A
为a
,B
为[ ]
,C
为[b]
。
现在让我们检查一下append(B, C, D)
的前提条件。这是append([ ], [b], D)
。再一次,使用第一条规则,我们可以看到D
也是[b]
。
所以Y
,第二个规则定义是[A|D]
。现在我们知道D
是[b]
,我们知道Y
是[a, b]
。
我只会做其中一个分手,因为它们基本上是一样的。
?- append(X,[b],[a,b]).
X = [ a ]
所以在这里,Prolog将返回X
唯一可能的值,以便语句返回true。我们来看看第二条规则。我们知道[a, b]
是[A|D]
。这意味着A
为a
,D
为[b]
。我们也知道C
是[b]
。所以现在,我们需要查看前提条件,找出B
是什么。 append(B, C, D)
转换为append(B, [b], [b])
。现在,使用第一条规则,我们知道B
必须是[ ]
。现在我们知道[A|B]
是[a|[ ]]
,它与[a]
相同。因此,X
必须为[a]
。
我希望这是一个详尽的解释。
答案 1 :(得分:0)
以下是我自己的理解。
您的代码描述了List的附加操作。
首先,这是一个缩写,可以帮助您理解prolog中的列表是什么以及|
的含义是什么:
[X1|[...[Xn|[]] = [X1,...Xn]
并附加(A,B,C)表示将列表B附加到A会导致C。
将A添加到空列表中的结果为A:
append([ ], A, A).
如果要将Y附加到X,请说添加(X,Y,_)。除非X是[],否则prolog不会知道任何事情。你必须通过说:
告诉规则append([A|B], C, [A|D]) := append(B, C, D)
然后prolog将尝试将X拆分为[A|B]
形式。然后Y将是A|D
,其中D是由C附加到B定义的列表。append(B, C, D)
是我们告诉prolog这个事实的方式。