# Trouble definining a function to use only certain heads

I'm trying to write a function that accepts only a particular Head (for example, prints only Symbols) using pattern matching. However, the following code has me a bit of confused.

> printer[foo_] := Print[foo]
> printer[1]
1


This behaviour makes sense: the _ matches the Integer (1) and the printer works. Now I redefine the printer function:

> printer[foo_Symbol] := Print[foo]
> printer[1]
1


Now _Symbol should not match an Integer and I would expect printer[1] to be returned.

To make matters worse, if I'd done this in the opposite order, first defining printer[var_Symbol] then changing the definition to printer[var_], I get the expected result.

What's going on?

(Mathematica 10.0.1.0 on 64-bit Ubuntu 14.04)

• Well, you have both definitions in context, and both definitions combine to mean, print anything, hence, the result you get. You'll have to clear printer first then redefine the second one only to get the behavior you want. Oct 14, 2014 at 3:24
• Look at the result of ??foo. That will show you all the all the rules that are in force for evaluating foo. Oct 14, 2014 at 5:02

What is going on is pretty simple: Mathematica does not forget your first definition because the pattern is different. This makes sense! Assume you define the faculty

fac[0] = 1;
fac[n_] := fac[n - 1]*n


and your second definition line would overwrite the first one. Then, nothing would work because you would have killed the end of the recursion.

To make matters worse, if I'd done this in the opposite order, first defining printer[var_Symbol] then changing the definition to printer[var_], I get the expected result.

is not true if you really did what you wrote. Let's define it the other way around:

ClearAll[printer]
printer[foo_Symbol] := Print[foo]
printer[foo_] := Print[foo]

printer[1]
(* 1 *)


Here, too, the 1 is printed. This makes perfect sense because when you look at the rule attached to printer

DownValues[printer]
(* {HoldPattern[printer[foo_Symbol]] :> Print[foo],
HoldPattern[printer[foo_]] :> Print[foo]} *)


you see that both definitions are there. Since the first one with foo_Symbol doesn't match, Mathematica tries the next one which matches.

So if you want to make that printer[1] stays unevaluated, you cannot define a general rule which matches. Clear all definitions of printer and use the foo_Symbol definition only.