4.8.7 Copying Terms

The meta-logical predicate copy_term/2 makes a copy of a term in which all variables have been replaced by brand new variables, and all mutables by brand new mutables. This is precisely the effect that would have been obtained from the definition:

copy_term(Term, Copy) :-
   recorda(copy, copy(Term), DBref),
   instance(DBref, copy(Temp)),
   Copy = Temp.

although the built-in predicate copy_term/2 is more efficient.

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. One of the uses of copy_term/2 is in writing interpreters for logic-based languages; with copy_term/2 available you can keep “clauses” in a Prolog data structure and pass this structure as an argument without having to store the “clauses” in the Prolog database. This is useful if the set of “clauses” in your interpreted language is changing with time, or if you want to use clever indexing methods.

A naive way to attempt to find out whether one term is a copy of another is shown in this example:

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, 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

Please note: If the term being copied contains attributed variables (see lib-atts) or suspended goals (see ref-sem-sec), those attributes are not retained in the copy. To retain the attributes, you can use:

copy_term(Term, Copy, Body)

which in addition to copying the term unifies Body with a goal such that executing Body will reinstate the attributes in the Copy. Copy as well as Body contain brand new (unattributed) variables only.

copy_term/2 is efficient enough to use without hesitation if there is no solution that does not require the use of meta-logical predicates. However, for the sake of both clarity and efficiency, such a solution should be sought before using copy_term/2. See mpg-ref-copy_term.

Send feedback on this subject.