Prolog中列表的深层副本

时间:2019-05-03 23:18:17

标签: list prolog

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

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

谢谢。

1 个答案:

答案 0 :(得分:0)

列表只是一个穿着化装的术语。

  • []是一个简单的原子。
  • [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],而不是 [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.