有人可以帮忙解释一下这个复制功能的工作原理吗?
Can someone please help explain this copy function works?
copyList([], []). % base case
copyList([H|T], [H|R]) :-
copyList(T, R).
我"sort of"明白递归是如何工作的,但是当我分析这个函数时,我真的很困惑。有人可以使用下面的示例逐步解释此函数中发生的事情以及它如何到达终点:
?- copyList([1,2,3],L).
要了解发生了什么,您必须将 Prolog 视为定理求解器:当您向 Prolog 提供查询 ?- copyList([1, 2, 3], L).
时,您实际上是在要求 Prolog 证明 copyList([1, 2, 3], L)
为真。
因此 Prolog 将尝试证明它。它有两个子句:
copyList([], []).
copyList([H|T], [H|R]):-
copyList(T, R).
因为它是第一个遇到的,Prolog 将尝试使用子句 copyList([], [])
.
来证明 copyList([1, 2, 3], L)
为真
这样做,并且由于子句没有正文(:-
之后没有任何内容),它只需要将查询的参数与子句的参数统一(统一 [1, 2, 3]
使用 []
和 L
使用 []
)。 L5
和[]
很容易统一(统一L5 = []
),[1, 2, 3]
和[]
是不可能统一的。因此,Prolog 无法使用其支配的第一个子句来证明您的查询。然后它必须尝试使用第二个。
它将再次将查询参数与子句参数统一起来,以查看该子句是否适用:在这里它可以这样做,统一 H = 1, T = [2, 3], L = [H|R]
。现在它必须查看是否满足 :-
之后列出的条件,因此它必须证明 copyList(T, R)
。完全相同的事情重复了两次,直到它发现自己试图证明 copyList([], R)
。在那里,第一个条款适用,它的工作结束了。
你可以用一张图总结执行过程如下:
copyList([1, 2, 3], L).
|
| try to use clause number 1, doesn't unify with arguments.
| use clause number 2 and L = [1|R]
|
` copyList([2, 3], R).
|
| try to use clause number 1, doesn't unify with arguments.
| use clause number 2 and R = [2|R2]
|
` copyList([3], R2).
|
| try to use clause number 1, doesn't unify with arguments.
| use clause number 2 and R2 = [3|R3]
|
` copyList([], R3).
|
| use clause number 1 and R3 = []. One solution found
| try to use clause number 2, doesn't unify with arguments.
| No more possibilities to explore, execution over.
现在执行结束了,我们可以通过统一链看到原来的L
是什么:
L = [1|R]
R = [2|R2]
R2 = [3|R3]
R3 = []
R2 = [3]
R = [2, 3]
L = [1, 2, 3]
感谢 Will Ness for his original idea 如何解释变量的最终值。
虽然您的具体问题已经得到解答,但评论不多。
首先,您也可以调用 ?- copyList(L,[1,2,3]).
或 ?- copyList([1,2,3],[1,2|Z]).
等。重要的是两个列表 可以 具有相同的长度,并且它们相应位置的元素可以相等(被统一),因为谓词的意思是它的两个参数列表是相同的——即长度相同,并且具有相同的元素.
例如,调用
可能会违反第一个条件
?- copyList(X, [A|X]).
因为它说第二个参数比第一个长一个元素。当然这样的解决方案不可能,但是查询永远不会终止,因为第一个子句永远不会匹配而第二个子句总是会。
copyList([], []). % base case
copyList([H|T], [H|R]) :-
copyList(T, R).
我"sort of"明白递归是如何工作的,但是当我分析这个函数时,我真的很困惑。有人可以使用下面的示例逐步解释此函数中发生的事情以及它如何到达终点:
?- copyList([1,2,3],L).
要了解发生了什么,您必须将 Prolog 视为定理求解器:当您向 Prolog 提供查询 ?- copyList([1, 2, 3], L).
时,您实际上是在要求 Prolog 证明 copyList([1, 2, 3], L)
为真。
因此 Prolog 将尝试证明它。它有两个子句:
copyList([], []).
copyList([H|T], [H|R]):- copyList(T, R).
因为它是第一个遇到的,Prolog 将尝试使用子句 copyList([], [])
.
copyList([1, 2, 3], L)
为真
这样做,并且由于子句没有正文(:-
之后没有任何内容),它只需要将查询的参数与子句的参数统一(统一 [1, 2, 3]
使用 []
和 L
使用 []
)。 L5
和[]
很容易统一(统一L5 = []
),[1, 2, 3]
和[]
是不可能统一的。因此,Prolog 无法使用其支配的第一个子句来证明您的查询。然后它必须尝试使用第二个。
它将再次将查询参数与子句参数统一起来,以查看该子句是否适用:在这里它可以这样做,统一 H = 1, T = [2, 3], L = [H|R]
。现在它必须查看是否满足 :-
之后列出的条件,因此它必须证明 copyList(T, R)
。完全相同的事情重复了两次,直到它发现自己试图证明 copyList([], R)
。在那里,第一个条款适用,它的工作结束了。
你可以用一张图总结执行过程如下:
copyList([1, 2, 3], L).
|
| try to use clause number 1, doesn't unify with arguments.
| use clause number 2 and L = [1|R]
|
` copyList([2, 3], R).
|
| try to use clause number 1, doesn't unify with arguments.
| use clause number 2 and R = [2|R2]
|
` copyList([3], R2).
|
| try to use clause number 1, doesn't unify with arguments.
| use clause number 2 and R2 = [3|R3]
|
` copyList([], R3).
|
| use clause number 1 and R3 = []. One solution found
| try to use clause number 2, doesn't unify with arguments.
| No more possibilities to explore, execution over.
现在执行结束了,我们可以通过统一链看到原来的L
是什么:
L = [1|R]
R = [2|R2]
R2 = [3|R3]
R3 = []
R2 = [3]
R = [2, 3]
L = [1, 2, 3]
感谢 Will Ness for his original idea 如何解释变量的最终值。
虽然您的具体问题已经得到解答,但评论不多。
首先,您也可以调用 ?- copyList(L,[1,2,3]).
或 ?- copyList([1,2,3],[1,2|Z]).
等。重要的是两个列表 可以 具有相同的长度,并且它们相应位置的元素可以相等(被统一),因为谓词的意思是它的两个参数列表是相同的——即长度相同,并且具有相同的元素.
例如,调用
可能会违反第一个条件?- copyList(X, [A|X]).
因为它说第二个参数比第一个长一个元素。当然这样的解决方案不可能,但是查询永远不会终止,因为第一个子句永远不会匹配而第二个子句总是会。