# Is there a concise form of Which or similar conditional?

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.

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

## 4 Answers

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


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] *)

• If you want periodicity: l[[Mod[i, Length[l], 1]]]. Jul 16, 2015 at 0:35

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)
}

• 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. Jan 15, 2013 at 10:03
• +1, you might want to use Replace instead of ReplaceAll for slightly more robustness when replacing unexpected expressions... Jan 15, 2013 at 11:19

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]

• 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. Jan 15, 2013 at 0:15
• @m_goldberg, I don't think it makes any difference.
– Rojo
Jan 15, 2013 at 1:49
• 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
– Rojo
Jan 15, 2013 at 1:51
• Ok, Forget what I said, I forgot that Red and friends actually evaluate to RGBColor
– Rojo
Jan 15, 2013 at 1:56
• One sleeps, magic happens. Jan 15, 2013 at 8:28