# 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 '15 at 21:08
• closely related: 1835 – Kuba May 18 '15 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. – m_goldberg May 18 '15 at 22:39

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:). – Algohi May 19 '15 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. – Mr.Wizard May 19 '15 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. – Algohi May 19 '15 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}