Prolog 赋值

Prolog assign value

a(1). 
a(5).
a(4).
b(1).
b(2).
b(3).
sa(X, Y) :- a(X), Y=a.
sb(X, Y) :- b(X), Y=b.
n([A,B,C], X) :- X=[].
n([A|B],[H|T]):-sa(A,H),n(B,T).
n([A|B],[H|T]):-sb(A,H),n(B,T).

我的查询:

n([1,2,3,4,5],X)

结果是 [a, b] 和 [b, b]。

我很难理解 [H|T] 部分,它到底是什么意思。 X 如何与 [H | 一起工作? T].我假设他们都以某种方式绑定到它。

首先,为了简化一点,这个:

sa(X, Y) :- a(X), Y=a.
sb(X, Y) :- b(X), Y=b.
n([A,B,C], X) :- X=[].

可以写成:

sa(X, a) :- a(X).
sb(X, b) :- b(X).
n([A,B,C], []).

我假设您无法理解谓词的递归行为。

通过执行 trace 和 运行 查询,您可以获得有关正在发生的事情的大量详细信息。但我们会尝试更高级别的演练。

考虑查询:

?- n([1,2,3,4,5],X).

您正在寻找 X 来实现这一点。 Prolog 将为该查询找到第一个匹配的谓词子句头。第一个 n/2 子句是:

n([A,B,C], []).

然而,这里的第一个参数是一个 3 元素的列表,而 [1,2,3,4,5] 是 5 个元素。所以没有匹配。下一个头是:

n([A|B], [H|T]) :- sa(A,H), n(B,T).

Prolog 尝试将 [A|B][1,2,3,4,5] 统一起来并成功,A = 1B = [2,3,4,5]。它还将 X[H|T] 统一起来,这也成功了。所以它会调用 sa(A,H),这是对 sa(1,H) 的调用。随后发生相同的过程(Prolog 将 sa(1,H)sa/2 的断言匹配),我将跳过细节,只说该查询的结果是 H = a。您可以在 Prolog 提示符下直接输入查询 sa(1,H) 来查看解决方案。

有了H = a,Prolog对sa(1,H)的调用就成功了,然后会调用n(B,T)也就是n([2,3,4,5], T)。跳过上面描述的一些细节,这会将 2 映射到 b,并导致递归调用 n([3,4,5], T)。现在 n([3,4,5], T) 匹配 n([A,B,C], []),所以它与 T = [] 匹配。因此,这种情况下的递归已经完成,结果是 X = [a,b]

由于 Prolog 将尝试找到所有解决方案,因此它将回溯到 sa(1,H) 调用并找到 H = b 作为解决方案,最终将导致 X = [b,b]

我在这里跳过了很多步骤,希望您能理解。遍历每一步很乏味,这就是为什么我建议使用 trace.