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 = 1
和 B = [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
.
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 = 1
和 B = [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
.