# Is using repeatedly a function that outputs its arguments efficient?

I understand that the title of the question might seem a little confusing so I will try to present an example of the actual problem instance.

Consider the following code snippet:

f[args__, warg___] := Module[{i=1, x, v},

While[

b[args, i],

x = h1[args];

v = g[x, warg];

h2[v];

i++

]

]


For all intents and purposes, you may treat h1 and h2 as functions defined elsewhere (in effect, they are just a bunch of expressions defined in the body of f, preceding and following the evaluation of g). Also, b is just a boolean expression needed in While. It depends on input argument(s) and the value of a step counter i.

The function f (which is more-or-less the workhorse of my code) has a number of input parameters. The inputs are divided into two group.

The first group, denoted with args__ in the code, consists of all those parameters needed in subsequent computations. The second group of inputs is denoted with warg___ ('w' for 'wildcard') and is actually a kind of switch.

When the warg parameter is present, function g executes and produces v (which is used in the rest of the code of f to produce the output). On the other hand, when the input argument warg is not present (the function f is called without it eg as in f[args], no warg present), function g- essentially-outputs its inputs ie x. Below is the (pseudo-)code definition for g.

g[arg_, warg_] := Module[{}

h3[arg, warg]

]

g[arg_] := arg


(Similarly, h3 is a shorthand for the body of g).

Now, where's the rub?

Well, the thing is that, although g is not expensive in terms of amount of computations performed, especially when it simply acts as a relay or an Identity transformation (spitting out x in the absence of warg), function f gets called a lot and g gets called that much more often (note how g is in a While loop in f).

So, I guess, the question is, if writing two separate versions of f (one including g and one simply calling h2[x] instead of v = g[x, warg] and then h2[v] in the case where warg is absent) would be more efficient than the current arrangement of using warg as a switch (and having the main loop try two different g's on for size every time). Obviously, in that former case, I would not need to have two definitions for g. Namely, the Identity transformation g[arg] := arg would not have a reason for being.

Having written down this question, and after some contemplation, I tend to favor the later approach (two f's, one g) for the simple reason that having the main loop decide which f to use many times is less expensive than doing the same thing for a lot more often with g, but I'd like to have a second opinion of more knowledgeable users.

As a post-script, please bear in mind that 'obsessing' over efficiency has to do with the fact that I'd like to port this code into a Manipulate at some point.

## 1 Answer

Let's do a quick test:

ClearAll[g, h]
g[arg_, warg_] := h[arg, warg]
g[arg_] := arg

ClearAll[f1, f2]
f1[arg_, warg___] := g[arg, warg]
f2[arg_] := arg

10^# & /@ Range[5, 6];
% // AssociationMap@Function[{n},
First@Timing[# /@ Range[n]] & /@ {f1, f2}
]

<|100 000 -> {1.04688, 0.421875}, 1 000 000 -> {9.375, 3.29688}|>


(For the purposes of the test I stripped away all but the two different types of f's and g's.)

It seems the first method is a factor of roughly 2 or 3 slower.

Unfortunately there's tension between writing code that looks the nicest (and uses the full power of Mathematica) versus code that performs best. Luckily, at least in this case, it's not too bad, so you can often get away with using the more aesthetically pleasing code.

• I thought so too; your assertion is spot on. – user42582 Sep 1 '17 at 13:51
• Thanks for the accept, but (following others around here) I like to encourage OP's to wait ~24 hours before accepting an answer, to encourage others to look at the question and likely give a better answer. – jjc385 Sep 1 '17 at 13:57
• I doubt anyone else is actively interested but I'll be the last one to break from tradition so I'll revoke it-for now; thanks! – user42582 Sep 1 '17 at 14:02