I'm quite sure this is an easy question but Im missing something.

I wish to define a function whose action depends on whether the input is a single matrix or a multiplication of two, For example:

I would want to do get:

(* x+y *)

(* x *)

Even though this example isn't interesting it is enough to demonstrate my issue.

I tried:

f[x_] := If[Head[Unevaluated[x]] == Times, 
(Unevaluated[x][[1]]) + (Unevaluated[x][[2]])

Indeed I get:

(* True*)

But I get:

(* If[Symbol == Times, Unevaluated[x][[1]] + Unevaluated[x][[2]], x] *)
(* If[Integer == Times, Unevaluated[7][[1]] + Unevaluated[7][[2]], 7] *)

Any explanation or an explanation of a better way to achieve my goal are welcome

  • $\begingroup$ See HoldAll and friends. $\endgroup$ – Kuba Aug 22 '17 at 14:14
  • $\begingroup$ SetAttributes[f, HoldFirst]? $\endgroup$ – J. M.'s technical difficulties Aug 22 '17 at 14:14
  • $\begingroup$ This doesn't help, tried it. Apparently the problem lies with the comparison Symbol==Times, and Integer==Times which for some reason doesn't evaluate to False. $\endgroup$ – Yair M Aug 22 '17 at 14:34
  • 1
    $\begingroup$ You should use SameQ (or === for short) when comparing e.g. Heads. This ensures that the comparison is always evaluated to True or False, and not left unevaluated $\endgroup$ – Lukas Lang Aug 22 '17 at 14:43


This answer explains why the problem in the question happens and how to solve it without changing the approach. Alucard's answer shows how to solve the problem with a more "Mathematica like" approach using SetDelayed with different patterns.

Original answer

A bit of an explanation of what I already said in the comments:

If you look at the output for f[x], you'll see that Symbol == Times has not been replaced by False. For this reason, the If expression is returned unevaluated.

This happens because Symbol andTimes don't have a value (although they are "known" symbols, they're treated as unknown variables for the sake of comparison since there are no OwnValues).

To always get either True or False, you can use SameQ (=== for short):

In[1]:=  Symbol === Times
Out[1]:= False
| improve this answer | |

you can use pattern matching

f[x_*y_] := x+y
f[x_] := x



gives you

x + y
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.