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
When you call
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
copy_term/2 is in writing interpreters for logic-based languages;
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
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, 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 ).
Please note: If the term being copied contains attributed variables (see lib-atts) or suspended goals (see ref-sem-sec), then 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.