2
$\begingroup$

I'm trying to quote a definition using DownValues, OwnValues, etc. Everything seems to be fine, except for temporary symbols' annoying appearance in recursive definitions: compare

In[1]:= With[{g = f}, {HoldPattern@g@x_ :> 2 + x}]
Out[1]= {HoldPattern[f[x_]] :> 2 + x}

and

In[2]:= With[{g = f}, {HoldPattern@g@x_ :> 2 + g@x}]
Out[2]= {HoldPattern[f[x$_]] :> 2 + f[x$]}

Here is my version of quoting a definition:

In[3]:= SetAttributes[InheritDefinition, HoldAll];

InheritDefinition[f_Symbol, g_Symbol, rules_:{}] :=
{ ClearAll@f
(*, InheritOptions[f, g]*)
, (#@f = With[{g = f}, Evaluate[#@g /. rules]])& /@
  {DownValues, OwnValues, SubValues, UpValues}
, FullDefinition@f } // Last

I don't see any need for temporary symbols here at all, since RuleDelayed is HoldRest, and HoldPattern is HoldAll. So, x$ is a dependency that seems totally unnecessary.

In[4]:= ClearAll /@ HoldComplete[oldF, newF] // ReleaseHold;

In[5]:= oldF@x_ := 2 - oldF[2 + x]

In[6]:= newF = "Will be overwritten";

In[7]:= InheritDefinition[newF, oldF]
Out[7]= newF[x$_] := 2 - newF[2 + x$]

        Attributes[x$] = {Temporary}

1) How to quote definitions without temporary symbols?

2) Why exactly is there a difference between In[1] and In[2]? Is it really because of recursion?

$\endgroup$
3
$\begingroup$

Why the renamings

It is probably easier to first answer your second question. The reason for what you see is that variable renaming (as a part of Mathematica's mechanism to emulate lexical scoping) is often excessive, in the sense that more symbols get renamed than strictly necessary.

Here is what is happening: lexical scoping constructs (Module, With, Function, SetDelayed) analyze the code inside, and if they sense variable collisions in inner scoping constructs (as a result of variable bindings they have to perform), they rename variables in inner scoping constructs. This is described in much more detail here. The excessive renaming is probably intended as a substitute for full code analysis, which makes sense for Mathematica, given that such full analysis would be very hard if not impossible, and also much more computationally intensive.

Cloning symbols

As to the second question, the most direct and effective answer was given here, and this is what I'd use if you are only interested in the end result.

If you want to understand the mechanics, then one example of doing something similar to what you want can be found here. In particular, the key ingredient is to use replacement rules:

setProp = (#[clone] = (#[s] /. HoldPattern[s] :> clone)) &

where clone is the symbol to inherit the definitions, and setProp is a function to be applied to DownValues, etc.

Since rule application does not care about possible naming conflicts, and just does what it is asked to do, you don't get the renaming this way. It has its downsides too, however: the other side of this is that, for example, pure functions with named arguments are a leaky abstraction in Mathematica. More on that can be found here and here (at the end of the post).

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.