试图理解递归序言程序?

时间:2012-09-28 05:01:33

标签: recursion prolog

这是教授讲座中的一个例子:

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概念都没有任何问题。没有提供进一步的解释,没有其他信息。这是所有的了。如果有人可以告诉我这个程序是如何运作的,我会爱他们直到死亡让我们分开。

2 个答案:

答案 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|[ ]],它们是相同的。所以现在我们可以回到第二条规则。 AaB[ ]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]。这意味着AaD[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这个事实的方式。