有人可以解释序言如何逐步解释这一点吗?
Can someone explain how prolog interprets this step by step?
您好,我拼命地试图从我的理解中理解这个片段,它设置了变量 X:1
,Z:[2,3]
。现在我不能再进一步了...
prefix([],X).
prefix([X|Y],[X|Z]):-prefix(Y,Z).
?-prefix(W,[1,2,3]).
Prolog 并不真正"set" 变量值。当您进行查询或使用统一运算符 =/2
.
时,它会尝试统一参数
让我们看看当您进行查询时 Prolog 中会发生什么。
?- prefix(W, [1,2,3]).
当您进行此查询时,Prolog 将开始搜索您断言的事实和谓词(包括那些在您的 Prolog 环境中预定义的)匹配的东西 prefix(W, [1,2,3]).
它遇到的第一个候选者是:
prefix([], X).
Prolog 尝试统一 W
与 []
,并成功统一 W = []
。然后它试图统一 [1,2,3]
和 X
。 X = [1,2,3]
也成功了。所以完整的子句成功了,你得到了这个查询的第一个解决方案:
W = [] ?
如果此时您按下 ;
,Prolog 将 回溯 如果有选择点,因为您有额外的 prefix/2
子句。所以 Prolog 回到那个点并尝试将 prefix(W, [1,2,3])
与 prefix([X|Y],[X|Z])
匹配。它试图统一W
和[X|Y]
并成功统一W = [X|Y]
(是的,在这一点上,这些都是可变的),并成功统一[1,2,3]
和[X|Z]
X = 1
和 Z = [2,3]
。这现在意味着 W = [1|Y]
(Y
仍未绑定)。由于这是谓词子句的头部,Prolog 将执行主体...
所以现在使用 W = [1|Y]
、X = 1
和 Z = [2,3]
,Prolog 将调用:
prefix(Y, Z).
换句话说,它将调用 prefix(Y, [2,3])
。由于现在这是对 prefix/2
的 "fresh" 查询,Prolog 再次从断言的事实和规则数据库的顶部开始搜索,并尝试将 prefix(Y, [2,3])
与 prefix([], X).
匹配。这成功了Y = []
和 X = [2,3]
。请记住:这是来自 prefix([X|Y], [X|Z])
的递归调用,所以让我们记下 prefix(Y, [2,3])
调用 returns 时的所有统一。我们有 X = 1
、Z = [2,3]
,现在 Y = []
。因此,在这种情况下,prefix([X|Y], [X|Z])
会以 X = 1
、Y = []
和 Z = [2,3]
成功。因此,原始调用 prefix(W, [1,2,3])
成功:
W = [X|Y] = [1|[]] = [1].
最后一次调用prefix(Y, [2,3])
留下了一个选择点,就像prefix(W, [1,2,3])
原来做的一样!因此,您可以使用与上述相同的逻辑追回那个人,直到您用尽所有成功的可能性。您最终将获得 W
.
的所有解决方案
我不会一一列举。那太长了,这是你的任务,不是我的。 :) 尝试理解我上面给出的关于Prolog如何搜索你的事实和规则的原则并自己尝试。
了解如何追踪谓词,了解如何从语义上阅读它也很有帮助。
prefix([], X).
这表示 []
是任何列表的前缀。从技术上讲,由于这是特定于列表的,因此可能更准确地写成:
prefix([], L) :- is_list(L).
或者...
prefix([], []).
prefix([], [_|_]).
否则,简单地使用 prefix([], _).
或 prefix([], X).
,像 prefix(P, 3)
这样的愚蠢的东西会成功 P = []
。
那么递归谓词:
prefix([X|Y], [X|Z]) :- prefix(Y, Z).
这表示,[X|Y]
是[X|Z]
的前缀ifY
是[=的前缀70=].
递归流程遵循此描述。
您好,我拼命地试图从我的理解中理解这个片段,它设置了变量 X:1
,Z:[2,3]
。现在我不能再进一步了...
prefix([],X).
prefix([X|Y],[X|Z]):-prefix(Y,Z).
?-prefix(W,[1,2,3]).
Prolog 并不真正"set" 变量值。当您进行查询或使用统一运算符 =/2
.
让我们看看当您进行查询时 Prolog 中会发生什么。
?- prefix(W, [1,2,3]).
当您进行此查询时,Prolog 将开始搜索您断言的事实和谓词(包括那些在您的 Prolog 环境中预定义的)匹配的东西 prefix(W, [1,2,3]).
它遇到的第一个候选者是:
prefix([], X).
Prolog 尝试统一 W
与 []
,并成功统一 W = []
。然后它试图统一 [1,2,3]
和 X
。 X = [1,2,3]
也成功了。所以完整的子句成功了,你得到了这个查询的第一个解决方案:
W = [] ?
如果此时您按下 ;
,Prolog 将 回溯 如果有选择点,因为您有额外的 prefix/2
子句。所以 Prolog 回到那个点并尝试将 prefix(W, [1,2,3])
与 prefix([X|Y],[X|Z])
匹配。它试图统一W
和[X|Y]
并成功统一W = [X|Y]
(是的,在这一点上,这些都是可变的),并成功统一[1,2,3]
和[X|Z]
X = 1
和 Z = [2,3]
。这现在意味着 W = [1|Y]
(Y
仍未绑定)。由于这是谓词子句的头部,Prolog 将执行主体...
所以现在使用 W = [1|Y]
、X = 1
和 Z = [2,3]
,Prolog 将调用:
prefix(Y, Z).
换句话说,它将调用 prefix(Y, [2,3])
。由于现在这是对 prefix/2
的 "fresh" 查询,Prolog 再次从断言的事实和规则数据库的顶部开始搜索,并尝试将 prefix(Y, [2,3])
与 prefix([], X).
匹配。这成功了Y = []
和 X = [2,3]
。请记住:这是来自 prefix([X|Y], [X|Z])
的递归调用,所以让我们记下 prefix(Y, [2,3])
调用 returns 时的所有统一。我们有 X = 1
、Z = [2,3]
,现在 Y = []
。因此,在这种情况下,prefix([X|Y], [X|Z])
会以 X = 1
、Y = []
和 Z = [2,3]
成功。因此,原始调用 prefix(W, [1,2,3])
成功:
W = [X|Y] = [1|[]] = [1].
最后一次调用prefix(Y, [2,3])
留下了一个选择点,就像prefix(W, [1,2,3])
原来做的一样!因此,您可以使用与上述相同的逻辑追回那个人,直到您用尽所有成功的可能性。您最终将获得 W
.
我不会一一列举。那太长了,这是你的任务,不是我的。 :) 尝试理解我上面给出的关于Prolog如何搜索你的事实和规则的原则并自己尝试。
了解如何追踪谓词,了解如何从语义上阅读它也很有帮助。
prefix([], X).
这表示 []
是任何列表的前缀。从技术上讲,由于这是特定于列表的,因此可能更准确地写成:
prefix([], L) :- is_list(L).
或者...
prefix([], []).
prefix([], [_|_]).
否则,简单地使用 prefix([], _).
或 prefix([], X).
,像 prefix(P, 3)
这样的愚蠢的东西会成功 P = []
。
那么递归谓词:
prefix([X|Y], [X|Z]) :- prefix(Y, Z).
这表示,[X|Y]
是[X|Z]
的前缀ifY
是[=的前缀70=].
递归流程遵循此描述。