2
$\begingroup$

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:

f[x*y]
(* x+y *)

f[x]
(* 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]])
,
x]

Indeed I get:

f[x*y]==x+y
(* True*)

But I get:

f[x]
(* If[Symbol == Times, Unevaluated[x][[1]] + Unevaluated[x][[2]], x] *)
f[7]
(* 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

$\endgroup$
4
  • $\begingroup$ See HoldAll and friends. $\endgroup$
    – Kuba
    Commented Aug 22, 2017 at 14:14
  • $\begingroup$ SetAttributes[f, HoldFirst]? $\endgroup$ Commented Aug 22, 2017 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
    Commented Aug 22, 2017 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
    Commented Aug 22, 2017 at 14:43

2 Answers 2

4
$\begingroup$

Note

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
$\endgroup$
3
$\begingroup$

you can use pattern matching

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

examples:

f[2*3]
f[x]
f[x*y]
f[5]

gives you

 5
 x
x + y
 5
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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