# Performance of pure function - Best way to define a function?

In general, to define a function, we often use f[x_]. Another way is to use pure function (full form and shorthand). I want to test the performance of these function declaration.

Original test:

Here is a simple test:

ClearAll[f1, f2, f3, f4];

f1[x_] = 3 x;
f2[x_] := 3 x;
f3 = Function[x, 3 x];
f4 = (3 #) &;

l1 = Range[10^7];

f1 /@ l1; // Timing
f2 /@ l1; // Timing
f3 /@ l1; // Timing
f4 /@ l1; // Timing

f1[l1]; // Timing
f2[l1]; // Timing
f3[l1]; // Timing
f4[l1]; // Timing


And here is a result:

{5.04688, Null}

{5.29688, Null}

{0.21875, Null}

{0.171875, Null}

{0., Null}

{0.015625, Null}

{0., Null}

{0., Null}


So here is what I've learned: (It's not new here, many people have shown it).

1. Use built-in Listability: f1[l1] is much faster than f1 /@ l1;

2. Pure function is the fastest solution f4 = (3 #) &; is faster than f3 = Function[x, 3 x];, and faster than f2[x_] := 3 x;

3. Searching the global rule definition is costly f2[x_] := 3 x; searching global rule is inside the loop.

f2 /@ l1; // Timing
{5.29688, Null}

f3 /@ l1; // Timing
{0.21875, Null}


Update 1: To avoid the built-in Listable over a list, I change the definition.

ClearAll[f1, f2, f3, f4];

f1[x_] = something[x];
f2[x_] := something[x];
f3 = Function[x, something[x]];
f4 = (something[#]) &;


Repeat these functions on a list:

l1 = Range[10^6];

f1 /@ l1; // Timing
f2 /@ l1; // Timing
f3 /@ l1; // Timing
f4 /@ l1; // Timing


Here is what I get:

{0.390625, Null}

{0.390625, Null}

{0.5, Null}

{0.296875, Null}


The pure function shorthand is the fastest. And the classic function declaration is very slow (50 times slower). I wonder why? Is it due to the x Pattern, or due to the difference between Set and SetDelay?

When do I need to do an intensive calculation, which type of function declaration I should use?

Conclusion: I found that using pure function is very fast. Adding the global rewrite rule in the inner loop is slow. Each time we define a new function, a rewrite rule is added. Term rewriting is expensive inside the loop. (For the built-in function, don't forget the Listability). For the complex function, use /@ combined with pure function.

• – kglr
Oct 28, 2020 at 10:27
• The function f1 doesn't work and is defined incorrectly. Try evaluating f1[1] to see what I mean. Oct 28, 2020 at 10:34
• oh, thank you. This is a duplicated question I think. Sorry for that. Oct 28, 2020 at 10:37
• Once f1 is reparied, you should also try f1[l1], f2[l1], f3[l1], and f4[l1] to become fully confused... ;) Explanation: Plus and Times have the attribute Listable which circumvents almost all of the calling overhead. Oct 28, 2020 at 11:12
• Thank you. :D. Most built-in Mathematica function is "internal listable", that's why they are so fast. By reading another post, I see that Function declaration is much faster than the global rewrite rule f[x_] Oct 28, 2020 at 11:27