# How can I efficiently define functions with different names but doing the same stuff?

Recently I have met with with this interesting question:How can I efficiently define functions with different names but doing the same stuff? Somebody may want to ask me why I want to do things like this, actually it is very much meaningful.

For example, there are 3 built-in functions in MMA: ContourIntegral[],ClockwiseContourIntegral[],CounterClockwiseContourIntegral[]. None of them has attached to any evaluation rules but they exist to stand for different external notations.

And what I am doing now is to define evaluation rules to those 3 integrals, or the so called "down values" of them. And I found that although with different names and external notations, when it comes to evaluation, they are the same: all of them are line integrals. As a result, the evaluation rules of them can also be the same both in their argument and functional body. But currently, I have to write 3 different lines doing the same thing, for instance:

ContourIntegral[x_]:=x^2+x;

ClockwiseContourIntegral[x_]:=x^2+x;

CounterClockwiseContourIntegral[x_]:=x^2+x;


(Since the name of the 3 integrals are somewhat long, I instead use f[], g[],h[] hereafter)

The way of coding above works, but verbose and wordy, since they are doing the same thing only with their function name different.

Moreover, when it comes to code maintenance, one change in code will lead you to modify code in 3 lines one by one. But if you can do it in one line, you can only change once in this very line to finish the maintenance efficiently.

To achieve this goal, I have tried to write in one line like :

(f||g||h)[x_]:=x^2+x;

(f|g|h)[x_]:=x^2+x;

(f[x_]||g[x_]||h[x_]):=x^2+x



Unfortunately, none of above works. And some of the error message:

So any idea on how to tell MMA that those functions doing the same thing but only with different names (or heads) in one line?

• To define identical functions with SetDelayed use(#[x_] := x^2 + x) & /@ {f, g, h}; Apr 22, 2022 at 15:42
• Thanks @BobHanlon, the way you suggested works like a charm. And one of the additional benefits of doing so is that: when it comes to code maintenance, previously one change in code will lead to modify code in several lines one by one. But with your method, the maintenance can be done in this very line efficiently. If you want more credit, you can make it a post and I will accept it. Apr 23, 2022 at 6:52

To define identical functions with SetDelayed use

(#[x_] := x^2 + x) & /@ {f, g, h};


This approach is also useful when formatting several indexed variables to display as subscripts, e.g.,

(Format[#[n_]] := Subscript[#, n]) & /@ {a, b, c};


Then,

Array[#, 5] & /@ {a, b, c}


You could do something like this:

BaseContourIntegral[x_] := x^2 + x;
ContourIntegral =
ClockwiseContourIntegral =
CounterClockwiseContourIntegral =
BaseContourIntegral;

• Also, this wouldn't actually work if ContourIntegral et al were actual built-in functions (at least not without unprotecting first), so I'm not sure what you meant in your original post. I assume it doesn't matter, but if there's more context here, then this might not work. Apr 22, 2022 at 15:35
• Thanks, but this way does not work even if ContouIntegral is not built-in and protected. Since different names exist to stand for different notations, when it comes to notation-related definitions, like the symbol of those integrals and Tex rules of the them, they need to have different names. Only when it comes to evaluation, they are the same. But the way you suggested has make all of them represented by BaseContourIntegral internally, when it comes to notation, they can not be distinguished any more. Apr 22, 2022 at 15:47
• They're just as distinguishable as they would be had you defined them explicitly as in your original post. Apr 22, 2022 at 16:16
• But of course, you can use DownValues instead of OwnValues, or whatever you want. It just sounds like there's some additional context that wasn't available for us to consider. Apr 22, 2022 at 16:42
• @AlbertLew All "value settings" are stored as value rules. The Standard Evaluation Sequence applies these rules in a certain order. You can block these rules with Block[{<symbol(s)>}, <code>]. You can't define anything without setting some sort of value, OwnValues[], DownValues[], UpValues[], SubValues[] etc. The different kinds of values are applied differently. You can override these rules (but not certain ones applied outside the standard sequence) by value setting, but the symbols do not go away. Apr 23, 2022 at 15:05

Just to show another perspective that could also work on multiple definitions.

Define your base function (which could have multiple definitions)

ClearAll[tempBase];

tempBase[x_] := x^2 + x;


now we manually add DownValues:

ClearAll[tempFn1, tempFn2];

Scan[(DownValues[#] =
DownValues[tempBase] /.
HoldPattern[tempBase] :> #) &, {tempFn1, tempFn2}];


If you do Trace, you see it work as if you define it yourself without replacing it with other symbols:

(* Base *)
tempBase[1] // Trace
(* Out: {tempBase[1],1^2+1,{1^2,1},1+1,2} *)

tempFn1[1] // Trace
(* Out: {tempFn1[1],1^2+1,{1^2,1},1+1,2} *)

tempFn2[1] // Trace
(* Out: {tempFn2[1],1^2+1,{1^2,1},1+1,2} *)


Note that, the above method will replace all the DownValues of your target function, if you want to preserve it just join it with the new DownValues.

If I understand your question correctly, this is how I usually implement this.

Clear[bI, cI, ccI, cccI]

bI[x_] := x^2 + x
cI[x_] := bI[x]
ccI[x_] := bI[x]
cccI[x_] := bI[x]
#[x] & /@ {cI, ccI, cccI}
(* {x + x^2, x + x^2, x + x^2} *)