克隆,复制序言列表

时间:2019-12-23 08:05:49

标签: prolog copy clone

我到处都可以找到这段代码,用于复制列表或克隆列表。

随处可见的代码:

clone([],[]).
clone([H|T],[H|Z]):- clone(T,Z).

?-clone([1,2,3],Z).
  Z=[1,2,3]

?-clone(2,Z).
  false

这不会复制lists以外的任何内容。以上代码的时间复杂度为O(n)

但是Prolog试图统一右侧并抬起一边,对吗?可以用更简单的方式来编写,对吧?

clone1(Z,Z).

clone1(Z,Z).

?-clone1([1,2,3],Z).
  Z=[1,2,3]
?-clone1(1,Z).
  Z=1
?-clone1(!,Z).
  Z =!
?-clone1(@,Z).
  Z=(@)

我觉得clone1(X, X).更为通用,几乎克隆了传递给它的所有内容。它没有克隆%()()clone1(%,Z)失败,并显示消息% - used for commentingclone1的时间复杂度为O(1),我可能是错的。在各个方面,clone1clone更好。

为什么此克隆/副本不是这样写的,即clone(X, X).我缺少什么?请向我解释我上面提供的两个代码之间的区别。如果两者都一样,为什么不使用clone1(X, X).并且没有人张贴过它。

2 个答案:

答案 0 :(得分:5)

要记住的一件事是“克隆”或“复制”的确切含义。变量会发生什么?

例如,如果您使用统一进行克隆,则:

| ?- L1 = [1,2,X], L2 = L1.

L1 = [1,2,X]
L2 = [1,2,X]

yes
| ?- L1 = [1,2,X], L2 = L1, X = a.

L1 = [1,2,a]
L2 = [1,2,a]
X = a

yes
| ?-

换句话说,通过统一,以这种方式“复制”或“克隆”的任何相应变量都保持统一(因为术语是统一的)。

如果您在“克隆”或“复制”时需要新变量,则可以使用Prolog的copy_term/2

| ?-  L1 = [1,2,X], copy_term(L1, L2), X = a.

L1 = [1,2,a]
L2 = [1,2,_]
X = a

yes
| ?-

所以现在L2L1的副本,它的变量位于列表的第3位。

答案 1 :(得分:2)

呼叫clone1(Z,Z2)与呼叫Z = Z2相同。哪个更基本。

正如您自己指出的,区别在于clone/2仅适用于列表,而=/2适用于所有有效的Prolog术语。

该代码的另一点是学习Prolog中的列表处理。它可以作为您可能要编写的其他递归列表处理任务的基础。例如映射,过滤,计数等。

Sterling和Shapiro的书将这种代码称为特定数据类型的骨架代码