我的例子是使用 append 仿函数:
append([],L,L).
append([H|T],L2,[H|L3]) :- append(T,L2,L3).
//append([123],[abc],L3). this is the query
真正让我困惑的是 [H|L3] 列表。形成我读到的内容,这会引起人们的注意,那么如何将其附加到列表中。当它在列表中递归并开始返回时,它是如何附加的?提前致谢。
该符号[H|T]
是 . 的语法糖'.'(H, T)
。所以它是一个有名字的函子.
——一个点和两个参数。考虑:
?- [1,2,3] = [X|L]。 X = 1, L = [2, 3]。
在这里我们问,是否有方程的解[1,2,3] = [X|L]
。而且,是的,这两个答案替换描述了一个解决方案。求解这个方程的过程称为统一。这个过程包含了数据结构的读取、选择和写入。所以,你可以称之为“脱头”,但你会错过背后的普遍性。毕竟:
?- X = 1,L = [2, 3],M = [X|L]。 X = 1, L = [2, 3], M = [1, 2, 3]。
在这里,我们从一个较小的列表中构建了一个新列表。但什么是:
?- M = [X|L]。 M = [X|L]。
这个答案暗示了许多解决方案。例如,所有长度为 1 和更长的列表。
由于您正在查看append/3
,请考虑以下查询:
?-附加(Xs,Ys,[X,Y,Z])。 ?-附加(Xs,Xs,Zs)。 ?-附加(Xs,Ys,Zs)
trace/0
当您想知道执行的样子时,您可以在这些情况下使用。
这是它的概述。
append([1, 2, 3], [a, b, c], L3).
[1, 2, 3]
不为空,则应用第二个子句append([2, 3], [a, b, c], L4).
并记住它的头L3
就像它的头,[1, 2, 3]
它的尾巴L3
是L4
[2, 3]
不为空,则应用第二个子句append([3], [a, b, c], L5).
并记住它的头L4
就像它的头,[2, 3]
它的尾巴L4
是L5
[3]
不为空,则应用第二个子句append([], [a, b, c], L6).
并记住它的头L5
就像它的头,[3]
它的尾巴L5
是L6
[]
与 结合[]
,应用第一个子句L6
与[a, b, c]
现在Prolog有所有的信息来回答你:
L6 = [a, b, c],
L5 = [3|L6],
L4 = [2|L5],
L3 = [1|L4].
将允许 Prolog 得出结论L3 = [1, 2, 3, a, b, c]
。
希望它有所帮助。
在 Prolog 中,你永远不会做任何像“起飞”那样活跃的事情。将其视为“专注于”可能会更好。(Prolog 本质上是声明性的;您不说要做什么,而是说某物的样子。)例如,列表可能是空的 ( []
) 或非空的 ( [H|T]
);每个非空列表都有一个 headH
和一个 tail T
,并且|
只是让您引用它们。根据需要,统一可以使用列表的声明[H|T]
来拆分列表或将列表放在一起。