2

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?

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
glS
  • 7,623
  • 1
  • 21
  • 61

2 Answers2

4

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.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • I like the way you explain things. If one wants to understand MMA deeply then he just need to follow your answers:). – Basheer Algohi May 19 '15 at 05: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 05: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. – Basheer Algohi May 19 '15 at 05:31
1
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}

Bob Hanlon
  • 157,611
  • 7
  • 77
  • 198