Consider the following (simplified for the purpose of example) definitions:
f[x_] := y /. y -> x
g[x_] := x
Where for example, the definition of f
could be motivated e.g. by first getting some expression (y
) from a previous calculation, and then deciding to make it into a function.
The problems begin when f is then passed on to a third function, that evaluates it many times (e.g. NIntegrate
, Plot
, etc), or maybe I then attempt to Compile
it. Due to the replacement rule that is saved as part of the definition, everything will be much slower, as can be seen in the following trace:
In[23]:= Trace[f[1]]
Out[23]= {f[1],y/. y->1,{y->1,y->1},y/. y->1,1}
vs
Trace[g[1]]
{g[1],1}
I suspect though I am not certain and haven't profiled this, that the first operation would be significantly slower even when compared to evaluating a more complex mathematical expression, provided it consists of built in functions. I'm open to this being refuted, but my interest is only partly driven by efficiency, so I won't accept an answer that simply refutes my assumption without answering the actual question (I would still find it useful, however).
Now, a plausible way to avoid the previous conundrum is to wrap the RHS of SetDelayed
by Evaluate
This has its own problems however, namely evaluating unintended parts:
In[16]:= z=1
Out[16]= 1
...
In[42]:= k[x_]:=Evaluate[z+y/.y->x]
In[35]:= Trace[k[1]]
Out[35]= {k[1],1}
In[44]:= Definition[k]
Out[44]= k[x_]:=1+x
What are other methods making the ReplaceAll evaluate once, and what (possibly unintended) consequences do they have? I am mainly interested in something lightweight, that I might actually use in notebooks without my init.m file - not in defining a largs expression to manipulate the SetDelayed lines (though that would still be interesting from an intellectual point of view).
Ideally, this would work (it doesn't) (f[x_]:=y)/.y->x
Thanks in advance!
k[x_]:=Evaluate[z+y/.y->x]
has the same effect ask2[x_]=z+y/.y->x
andk3[x_]:=z+x
. (CheckDownValues/@{k,k2,k3}
) 2. Function definition based on pattern matching can't be compiled directly, for more information you may want to read this. $\endgroup$ – xzczd Oct 10 '16 at 15:08Set
and notSetDelayed
there):{HoldPattern[k[x_]] :> 1 + x, HoldPattern[k2[x_]] :> 1 + x, HoldPattern[k3[x_]] :> z + x}
and that was precisely the point - I want to get fromk[x_]:=y+z
tok[x_]:=x+z
rather than tok[x_] = x+z
$\endgroup$ – Shwouchk Oct 10 '16 at 15:27y
be replaced whilez
be unevaluated. I think this should stated in a clearer way in the body of the question. As to this specific example, a solution I can think out is:Unevaluated@(k[x_] := y + z) /. y -> x
$\endgroup$ – xzczd Oct 10 '16 at 16:04f[x_] := z + y /. y -> x
too slow when used like this (z
becomes a number eventually?):Plot[f[x], {x,-1,1}]
? Even if that's true... I don't think I quite understand you because of thez
. Can you provide a next-to-minimal example? $\endgroup$ – QuantumDot Oct 11 '16 at 2:08