I wrote some Mathematica code that defines a function I want to use repeatedly (f
) inside another function (finit
) that pre-calculates some of the parameters needed for subsequent evaluations of the inner function. This arrangement is more computationally efficient than putting both steps into one function and it allows for the inner function's argument list to be simpler by focusing only on the parameters that vary from one call to the next.
The arrangement is inspired by and meant to roughly mimic how the corresponding algorithm in C++ is written. In that case I have a class with a constructor (like finit
) and a class member function (like f
). When a new object of the class is instantiated, a single call to the constructor does all the initialization work whose results are then available to the object every time the member function is called.
Here is a bare bones example to illustrate the basic idea:
finit[x_]:=
Module[{X},
X=x;
Clear[f];
f[y_]:=X+y;
]
In this example, X=x
represents the steps that initialize some internal parameters {X
} based on the arguments to finit
and f
is the 'worker' function that combines those internal parameters with its own calling arguments to produce some new result. Every call to finit
resets X
and redefines f
. For example,
finit[a]
f[b]
finit[c]
f[d]
returns
a+b
c+d
I'd like to be able to temporarily change the initialization parameters, run f
several times, then go back to the original parameters without having to resupply them to a new call to finit
.
This is easy in C++. All I have to do is instantiate two objects using different constructor arguments. Each object has a different name and I can call either one without affecting the other. I can't do that with the Mathematica code as written.
I would be satisfied if the temporary definition were restricted to the inside of a Block
or Module
.
[Of course, I could make new functions (e.g., ginit[x_]
and g[y_]
) that do exactly the same thing but I'm looking for an approach that avoids the need to duplicate large blocks of code.]
So far the only way I've found to do this is to put the guts of finit
and f
into their own (memoryless) functions (e.g., body1
& body2
) as shown below:
SetAttributes[body1,HoldAll]
body1[X_,x_]:=(X=x)
body2[X_,y_]:=(X+y)
finit[x_]:=Module[{X},body1[X,x];Clear[f];f[y_]:=body2[X,y]]
finit[a]
{f[b],f[c],f[d]}
Module[{Y,f},body1[Y,α];Clear[f];f[y_]:=body2[Y,y];Times@@{f[β],f[γ],f[δ]}]
{f[b],f[c],f[d]}
Run the above and you get
{a+b,a+c,a+d}
(α+β) (α+γ) (α+δ)
{a+b,a+c,a+d}
which shows that (global) f
retains its original definition even though the (local) f
inside the second Module
is defined differently.
This works, but is kludgy and inefficient. I'm not really satisfied with this solution.
Is there a more elegant way to do this that makes better use of Mathematica's wide ranging capabilities (Blocks
, Contexts
, etc.), maintains the simplicity and efficiency of the original method, yet avoids verbatim code copying?