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)), erase(DBref), 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
.