# Evaluation speed of apparently equivalent functions

Consider the following expressions:

f[x_Integer] := x,
f[x_] := x /; x ∈ Integers,
f[x_?IntegerQ] := x


All of the expressions above (and probably others which I don't know) seem to do the exact same thing.

However, what I'm curious to know is: are they really equivalent, or are there circumstances where one is preferable (faster, slower?) over the other?

• Do a Trace on each, s/b/ illuminating...
– ciao
May 18, 2015 at 21:08
• closely related: 1835
– Kuba
May 18, 2015 at 21:09
• I would be surprised if [x_Integer] := x were not the fastest of the examples you give, for the simple reason that it requires the least effort to determine whether the actual argument passed matches the argument pattern. May 18, 2015 at 22:39

## 2 Answers

In version 10.1 timings are pretty much as I expected:

f1[x_Integer] := x;
f2[x_] := x /; x ∈ Integers;
f3[x_?IntegerQ] := x;

First @ Timing @ Do[#[i], {i, 1*^6}] & /@ {f1, f2, f3}

{0.374402, 1.06081, 0.499203}


As m_goldberg commented _Integer should be fastest as unlike the others it does not require evaluation; it directly matches the ("implicit") head of the argument. This difference becomes more important with functions that hold their arguments.

SetAttributes[{f1, f2, f3}, HoldAll]

foo := Print["pop!"]


With f1 the Print does not evaluate:

f1[foo];  (* nothing printed *)


With f2 and f2 it does:

f2[foo];
f3[foo];


pop!

pop!

That also results in this evaluation behavior:

z = 1;

f1[z]
f2[z]
f3[z]

f1[z]

1

1


f1 matches only an explicit integer and z is not but since f2 and f3 evaluate their arguments in the course of pattern matching the assigned value of z is used, matched, and returned.

• I like the way you explain things. If one wants to understand MMA deeply then he just need to follow your answers:). May 19, 2015 at 5:17
• @Algohi Thanks! Several people have suggested I write a book on Mathematica. Recently I am beginning to consider that seriously. Feedback on what is clear or useful in my answers and what is confusing, needless, or simply wrong is appreciated. May 19, 2015 at 5:28
• That would be great help from you to the community. I strongly support the idea you write a book and I will be waiting to read it. May 19, 2015 at 5:31
f1[x_Integer] = x;
f2[x_] = x /; x \[Element] Integers;
f3[x_?IntegerQ] = x;

Timing[f1 /@ Range[10^6];]


{0.424561, Null}

Timing[f2 /@ Range[10^6];]


{0.69525, Null}

Timing[f3 /@ Range[10^6];]


{0.630597, Null}