#### 11.3.44 `copy_term/[2,3]`

*ISO*

#### Synopsis

`copy_term(``+Term`, `-Copy`)

Unifies `Copy` with a copy of `Term`
in which all variables have been replaced by brand new variables,
and all mutables by brand new mutables.

`copy_term(``+Term`, `-Copy`, `-Body`)

Furthermore, if `Term` contains variables with goals blocked on
them, or variables with attributes that can be interpreted as a goal
(see lib-atts), then `Body` is unified with the conjunction of
such goals. If no such goals are present, then `Body` is unified with
the atom `true`

. The idea is that executing `Body`
will reinstate blocked goals and attributes on the variables in `Copy`
equivalent to those on the variables in `Term`.

#### Arguments

`Term`
*term*

`Copy`
*term*

`Body`
*callable*

#### Description

Independent copies are substituted for any mutable terms in
`term`. It behaves as if defined by:

copy_term(X, Y) :-
assert('copy of'(X)),
retract('copy of'(Y)).

The implementation of `copy_term/2`

endeavors to conserve space
by not copying ground subterms.

When you call `clause/[2,3]`

or `instance/2`

, you get a new copy
of the term stored in the database, in precisely
the same sense that `copy_term/2`

gives you a new copy.

#### Examples

- A naive way to attempt to find out whether one term is a copy of another:
identical_but_for_variables(X, Y) :-
\+ \+ (
numbervars(X, 0, N),
numbervars(Y, 0, N),
X = Y
).

This solution is sometimes sufficient, but will not work if the two
terms have any variables in common.

- If you want the test to succeed even when the two terms do have
some variables in common, then you need to copy one of them; for example,
identical_but_for_variables(X, Y) :-
\+ \+ (
copy_term(X, Z),
numbervars(Z, 0, N),
numbervars(Y, 0, N),
Z = Y
).

- An example of
`copy_term/3`

. Suppose that you want to make `copy_term/3`

aware of the attribute `tfs/1`

in some module. Then with the module-file:
:- module(foo, []).
:- use_module(library(atts)).
:- attribute tfs/1.
attribute_goal(X, put_atts(X,tfs(Y))) :-
get_atts(X, tfs(Y)).

the following query works:

| ?- `foo:put_atts(X, tfs(ind)), copy_term(f(X), Copy, Body).`
Body = foo:put_atts(_A,tfs(ind)),
Copy = f(_A),
put_atts(X,tfs(ind)) ? RET
yes

#### Comments

`copy_term/2`

is part of the ISO Prolog standard; `copy_term/3`

is not.

#### Exceptions

None.

#### See Also

ref-lte-cpt.

Send feedback on this subject.