克隆、复制序言列表

Ch3*_*teR 2 clone copy prolog

我发现这段代码无处不在,用于复制列表或克隆列表。

随处可见的代码:

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

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

?-clone(2,Z).
  false
Run Code Online (Sandbox Code Playgroud)

这不会复制除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=(@)
Run Code Online (Sandbox Code Playgroud)

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

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

lur*_*ker 6

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

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

| ?- 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
| ?-
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

yes
| ?-
Run Code Online (Sandbox Code Playgroud)

所以现在L2是一个副本,L1在列表的第三个位置有它自己的变量。

  • 学到了一些新东西“copy_term/2”。这个答案内容丰富。感谢您抽出时间。 (2认同)