11
$\begingroup$

Suppose that I want to write a function fun that takes an Integer num as input, and returns Red if num == 1, Orange if num == 2, and Yellow if num == 3. One way, I think, to do this is to use Which:

fun[num_Integer] := Which[num == 1, Red, num == 2, Orange, num == 3, Yellow]

Is there a more concise way to write fun? In other words, is there any built-in function (analogous to Which) that I can use that would allow me to avoid typing "num" all the time instead of always having to specify it to Which. Writing fun as a series of nested If statements would be even lengthier.

Do you have any suggestions? Thanks for your time.

$\endgroup$
3
  • 1
    $\begingroup$ I usually use Switch as per @jVincent below $\endgroup$ Jan 14, 2013 at 23:00
  • $\begingroup$ Every single one of the methods I thought of are already in the four answers below. That doesn't happen often. Nice coverage guys! $\endgroup$
    – Mr.Wizard
    Jan 15, 2013 at 2:46
  • 1
    $\begingroup$ We probably need to add PiecewiseColor. $\endgroup$ Jul 15, 2015 at 22:19

4 Answers 4

29
$\begingroup$

Not really a concise syntax, but you can also do this using Switch, which removes the need for writting the checking, and also allows patterns:

fun[num_Integer] :=
  Switch[num,
  1, "Red",
  2, "Orange",
  3, "Yellow",
  _?PrimeQ, "Purple",
  _, "LightGray"]

I used strings just to make the output nicer to verify the behavior. Naturally you would switch these to the actual colors.

Style[#, fun@#] & /@ Range@20

Numbers colored using the function

$\endgroup$
26
$\begingroup$

For example you may do something like

f[i_] := {Red,Orange,Yellow}[[i]]

Edit

You can easily add some robustness:

f[l_List, i_Integer ] := l[[i]] /; 1 <= i <= Length@l;

ll = {Red, Orange, Blue};
f[ll, 3]
(* RGBColor[0, 0, 1] *)
$\endgroup$
1
18
$\begingroup$

You could use ReplaceAll to write your function this way:

fun[num_Integer] := num /. {1 -> Red, 2 -> Orange, 3 -> Yellow}

This also allows pattern matching, and works better than switch in case you want to name parts of your pattern:

findpeople[dbconn_, name_] := DBSelect[dbconn, "People", name] /. {
   $Failed :> (Message[findpeople::conn]; $Failed),
   {} :> (Message[findpeople::empty]; $Failed),
       results_List :> results,
       other_ :> (Message[findpeople::err, other]; $Failed)
}
$\endgroup$
2
  • 2
    $\begingroup$ Big +1. Not enough love for this answer, folks! The possibility to transparently incorporate error-handling is very valuable. I use similar constructs a lot too. $\endgroup$ Jan 15, 2013 at 10:03
  • 3
    $\begingroup$ +1, you might want to use Replace instead of ReplaceAll for slightly more robustness when replacing unexpected expressions... $\endgroup$ Jan 15, 2013 at 11:19
15
$\begingroup$

One simple solution is:

fun[1] = Red;
fun[2] = Orange;
fun[3] = Yellow;

A more complex solution that accepts arbitrary equivalence lists at run time:

fun[{ins_, outs_}] :=  Function[x, Piecewise[MapThread[{#2, x == #1} &, {ins, outs}], x]];

f = fun[{{1, 2, 3}, {Red, Orange, Yellow}}];

f[2]

RGBColor[1, 0.5, 0]

$\endgroup$
9
  • 4
    $\begingroup$ I think it is a little more efficient to use fun[1]=Red,etc. Using := means that the token Red will evaluated on every call to fun, rather than once. $\endgroup$
    – m_goldberg
    Jan 15, 2013 at 0:15
  • $\begingroup$ @m_goldberg, I don't think it makes any difference. $\endgroup$
    – Rojo
    Jan 15, 2013 at 1:49
  • $\begingroup$ If you do f[_]=x; x=2;, then f[9] will have to reevaluate x regardless of having used an immediate assignment. If MMA is smart enough to not check when the assignment is to an atom, them it probably is also smart enough with a delayed assignment. But I'm not certain $\endgroup$
    – Rojo
    Jan 15, 2013 at 1:51
  • 1
    $\begingroup$ Ok, Forget what I said, I forgot that Red and friends actually evaluate to RGBColor $\endgroup$
    – Rojo
    Jan 15, 2013 at 1:56
  • 2
    $\begingroup$ One sleeps, magic happens. $\endgroup$ Jan 15, 2013 at 8:28

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.