【问题标题】:Deep copy of a list in PrologProlog中列表的深层副本
【发布时间】:2019-05-03 23:18:17
【问题描述】:

我正在尝试复制一个列表,以便我在新列表上执行的任何操作都不会更改原始列表。我看过prolog, copying lists 和Prolog - copy a piece of list。但是,这些选项都不会生成与其“父级”“独立”的列表。

来自命令式背景,一些 Prolog 概念很难掌握,我敢肯定我在这里遗漏了一些东西。所以我的问题是是否可以在 Prolog 中创建列表的深层副本?

提前谢谢你。

【问题讨论】:

  • 你试过copy_term/2吗?如果您是 Prolog 的新手,不知道为什么需要这样的东西。
  • 您不需要 ground 的列表副本。无论如何,它们是不可变的。您不能对列表执行任何修改“操作”。 (嗯,你可以,但这会让你深入到非回溯、非逻辑领域。)除非你描述一个特定的用例,否则甚至很难开始回答你的问题。你将如何使用这个“深拷贝”?你在解决什么问题,你使用什么算法,你是如何在 Prolog 中实现它的?然后我们有一些现实的例子可以建立。

标签: list prolog


【解决方案1】:

列表只是穿着华丽服装的术语。

  • [] 是一个简单的原子。
  • [a] 是术语 .(a,[]) 的语法糖
  • [a,b] 是术语 .(a,.(b,[])) 的语法糖。
  • [H|T] 是术语 .(H,T) 的语法糖

仅此而已。保留括号和句点,确实如此。

因此,您所说的实际上与列表无关,而是与术语有关。如果所讨论的术语是完全绑定的——意味着它以及递归地任何子术语不包含任何非统一变量,则该术语是不可变的。但如果它包含任何未绑定的变量,它就是可变的。

所以,您所说的是执行递归树遍历来克隆一个术语,用新副本替换任何未绑定的变量。诀窍是您需要映射遇到的每个变量及其替换。所以像 [A,A,B,B,foo(A,B,C),C] 这样的东西会以 [X,X,Y,Y,foo(X,Y,Z),Z] 和 not [V1,V2,V3,V4,foo(V5,V6,V7),V8] 出现。

幸运的是,Prolog 带有内置工具:copy_term/2。

但我想你的导师并不是要你使用它。

遍历任意项并不困难。类似这样的东西(目前没有方便的 Prolog):

clone_deep( T , C ) :- clone_deep( T, [], C, _ ).

% T: source term
% S: symbol table
% C: cloned term
% S1: [possibly] extended symbol table

clone_deep( T , S , C, S1 ) :-
  var(T),                       % term is a variable
  map_var(T,S,C,S1)             % fetch/add its mapping to the symbol table.
  .
clone_deep( T , S , T , S ) :-
  atomic(T)                     % term is atomic (number, atom, etc.)
  .
clone_deep( T , S , C, S1 ) :-
  compound(T),                  % term is a compound term  like foo() or foo(X,Y).
  T =.. [Functor|Args],         % decompose it into its functor and its argument list
  clone_deep(Args,S,Args1,S1),  % recursively clone its arguments
  C =.. [Functor|Args1]         % recompose the new compound term
  .

% recursively run down the list of symbol mappings to find the self-same variable
% add it if not found.

map_var( V , [ X:C | S ] , C , [ X:C | S ] ) :- X  == V, !. % V is the same ref as X -- already in symbol table
map_var( V , [ X:Y | S ] , C , [ X:Y | Z ] ) :- X \== V, !, % V and X are different refs
  fresh_symbol(V,S,C,Z).                                    %
map_var( V , []          , C , [ X:C     ] ).               % not yet mapped var.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-09
    • 2016-06-21
    • 1970-01-01
    • 2016-01-29
    • 1970-01-01
    • 1970-01-01
    • 2018-07-12
    • 1970-01-01
    相关资源
    最近更新 更多