# A function that modifies functions - well-defined operation?

Here's my basic setup:

Say I have a list of specific symbols and a function noSymbol, which accepts a mathematica expression and checks whether any symbol from my list is contained in it, for example:

symbols = {basisElement};
noSymbol[x_] := And @@ ( Length[Position[x, #]] === 0 & /@ symbols );


An examle use-case could be that basisElement is a function enumerating basis vectors of some n-dimensional algebra, so that I could define the multiplication of the algebra as

mult[basisElement[i_], basisElement[j_]] := Sum[strucConst[i, j, k] * basisElement[k], {k, 1, n}];


with structConst the structure constants of the algebra.

Of course in this situation it is natural to define linear functions, and what I would often find myself doing is

Clear[f];
f := 0;
f[v_ + w_] := f[v] + f[w];
f[a_ * v_] := a * f[v] /; noSymbol[a];
f[v_ * a_] := a * f[v] /; noSymbol[a];
(* actual function definition *)


at the beginning of every definition of a linear function.

This adds a lot of repetition to my code, so I wanted to ask if using a "linearizing function" like

linearize[f_] := (
f := 0;
f[v_ + w_] := f[v] + f[w];
f[a_ * v_] := a * f[v] /; noSymbol[a];
f[v_ * a_] := a * f[v] /; noSymbol[a];
);

Clear[f];
linearize[f];
(* actual function definition *)


is considered good practices and makes sense, or if it could lead to any serious issues.

EDIT: Additionally, if this is good practice, how can I extend my linearize function so that it can "multilinearize"? For example, my multiplication from above would have to be linear in each argument.

First, a note regarding noSymbol: You can more easily implement it using FreeQ:

symbols = Alternatives[basisElement];
noSymbol := FreeQ[symbols]


Also, you don't need to define both f[a_ * v_] and f[v_ * a_], since Times is Orderless.

As for the actual question: I don't see any reason why this shouldn't be done, in fact, I've used very similar functions in the past.

Finally, for multi-linearization: You can do something like the following:

linearize[f_] := (
f[___, 0, ___] := 0;
f[pre___, v_ + w_, post___] := f[pre, v, post] + f[pre, w, post];
f[pre___, a_ * v_, post___] := a*f[pre, v, post] /; noSymbol[a];
);

Clear[f];
linearize[f];

f[a basisElement, c + d]
(* a f[basisElement, c] + a f[basisElement, d] *)


The rules simply apply the linearity properties to any argument, while keeping all the others (if any exist) unmodified

• Thanks, I have never heard of FreeQ. Also, d'oh... the solution for multilinearization is so simple haha Jun 23, 2021 at 16:15
• @JoMo FreeQ[symbols] is equivalent to FreeQ[#, symbols]& (note the order of the arguments) - this is also mentioned in the third usage form in the documentation of FreeQ (and in case you were not aware: similar so called "operator forms" exist for many functions, e.g. Map, Position, ...) Jun 23, 2021 at 16:21