title: Copy term with variables without variables being bound
body: <p>With SWI-Prolog.</p>
  
  <p>How can a term with variables be copied without the variables being bound?</p>
  
  <h2>What I have tried</h2>
  
  <p>I tried <a href="http://www.swi-prolog.org/pldoc/man?predicate=copy_term/2" rel="nofollow noreferrer">copy_term/2</a> and <a href="http://www.swi-prolog.org/pldoc/man?predicate=duplicate_term/2" rel="nofollow noreferrer">duplicate_term/2</a></p>
  
  <p>For example:</p>
  
  <pre class="lang-erlang prettyprint-override"><code>foo(c).
  
  foo(E) :-
      E = bar(a,b,X),
      copy_term(E,Ec),
      duplicate_term(E,Ed),
      write("E:  "),write(E),nl,
      write("Ec: "),write(Ec),nl,
      write("Ed: "),write(Ed),nl.
  </code></pre>
  
  <p>results in</p>
  
  <pre class="lang-erlang prettyprint-override"><code>?- foo(bar(a,b,bar(a,b,bar(a,b,c)))).
  E:  bar(a,b,bar(a,b,bar(a,b,c)))
  Ec: bar(a,b,bar(a,b,bar(a,b,c)))    &lt;-- Copy
  Ed: bar(a,b,bar(a,b,bar(a,b,c)))    &lt;-- Duplicate
  true.
  
  ?- foo(bar(a,b,bar(a,b,c))).
  E:  bar(a,b,bar(a,b,c))
  Ec: bar(a,b,bar(a,b,c))    &lt;-- Copy
  Ed: bar(a,b,bar(a,b,c))    &lt;-- Duplicate
  true.
  
  ?- foo(bar(a,b,c)).
  E:  bar(a,b,c)
  Ec: bar(a,b,c)    &lt;-- Copy
  Ed: bar(a,b,c)    &lt;-- Duplicate
  true.
  </code></pre>
  
  <p>and checked the section <a href="http://www.swi-prolog.org/pldoc/man?section=manipterm" rel="nofollow noreferrer">Analyzing and Constructing Terms</a></p>
  
  <h2>What I need</h2>
  
  <p>Here <code>En</code> is the result of predicate returning what I need</p>
  
  <pre class="lang-erlang prettyprint-override"><code>?- foo(bar(a,b,bar(a,b,bar(a,b,c)))).
  E:  bar(a,b,bar(a,b,bar(a,b,c)))
  En: bar(a,b,X),                      &lt;-- Need this
  true.
  
  ?- foo(bar(a,b,bar(a,b,c))).
  E:  bar(a,b,bar(a,b,c))
  En: bar(a,b,X),                      &lt;-- Need this
  true.
  
  ?- foo(bar(a,b,c)).
  E:  bar(a,b,c)
  En: bar(a,b,X),                      &lt;-- Need this
  true.
  </code></pre>
  
  <p>I was hoping for a built-in predicate.</p>
  
  <h2>TL;DR</h2>
  
  <p>The need for this is in solving binary expressions. The original is used to select the predicate and to solve the expression. A copy I refer to as local is used to show the rewrite for the subexpression and a copy I refer to as global is used to show the rewrite applied to the entire expression. If there is only one term, e.g. no copies, once the variable is bound for one use, it causes the other uses to fail.</p>
  
  <p>The current solution is to type in the multiple terms with different variables for each use into the predicate. Multiply this by hundreds to possibly thousands of predicates with possible typing or copy/paste mistakes and you can see the need. </p>
  
  <h2>Other considerations</h2>
  
  <p>I have also considered having a master copy of the term in the predicate and then using that to make the three copies. The problem with that is one of the copies is used in selecting the predicate, so before a predicate can be selected the copy would have to take place. So even if a predicate is not selected for evaluation a copy has to take place in the predicate.</p>
  
  <pre class="lang-erlang prettyprint-override"><code>foo(c).
  
  foo(Ec) :-
      M = bar(a,b,X),
      copy_term(M,Ec),
      duplicate_term(M,Ed),
      write("M:  "),write(M),nl,
      write("Ec: "),write(Ec),nl,
      write("Ed: "),write(Ed),nl.
  
  ?- foo(bar(a,b,bar(a,b,bar(a,b,c)))).
  M:  bar(a,b,_9364)
  Ec: bar(a,b,bar(a,b,bar(a,b,c)))
  Ed: bar(a,b,_9384)
  true.
  
  ?- foo(bar(a,b,bar(a,b,c))).
  M:  bar(a,b,_9240)
  Ec: bar(a,b,bar(a,b,c))
  Ed: bar(a,b,_9260)
  true.
  
  ?- foo(bar(a,b,c)).
  M:  bar(a,b,_9116)
  Ec: bar(a,b,c)
  Ed: bar(a,b,_9136)
  true.
  </code></pre>
  
  <p>So<br>
  <code>copy_term/2</code> gives me the copy with the variables bound which is needed for the predicate selection and evaluation part
  <code>duplicate_term/2</code> gives me the term with the free variables for use with other predicates.</p>
  
  <h2>Example output from actual application</h2>
  
  <pre class="lang-erlang prettyprint-override"><code>                    Global                           Local
                      ------------------               -----------------------------
  Input               (1 + ((0 + 0) + 0)) 
  0 + X -&gt; X                                           (0 + 0)                -&gt; 0
  =                   (1 + (0 + 0))       
  X + 0 -&gt; X                                           (0 + 0)                -&gt; 0
  =                   (1 + 0)             
  X + 0 -&gt; X                                           (1 + 0)                -&gt; 1
  =                   1                   
  </code></pre>