Is it correct that the Select equivalent of Cases is missing for Switch?

I mean a function switch[conditionFunction,form1,value1,form2,value2,...]. Where conditionFunction would be a function that evaluates to True or False on the various forms, and switch would return the first value for which conditionFunction[form] evaluates to True.

What should I be using for this? If nothing pre-exists, what would be the best way to implement this.? (And why is this missing if we do have both Select and Cases by default?)

  • $\begingroup$ Perhaps Whichis the function you're looking for. $\endgroup$ – Ulrich Neumann Nov 4 '18 at 16:42
  • $\begingroup$ @UlrichNeumann, no, I don't want to have repeat the same test to be applied to all the forms. I do think that it is easy to write what I want using Which, with which I was already familiar, so I should have mentioned it in my question anyway. $\endgroup$ – Kvothe Nov 4 '18 at 17:14
  • 2
    $\begingroup$ Which repeats testing until the first True is detected! $\endgroup$ – Ulrich Neumann Nov 4 '18 at 17:50
  • $\begingroup$ Sorry that comment wasn't too clear. I meant since the test would be the same I don't want to have to type it for every entry just changing the argument. (That's better for readability and not just to save on the typing.) $\endgroup$ – Kvothe Nov 5 '18 at 9:43
switch // Attributes = { HoldRest };

switch[foo_, spec__] /; EvenQ @ Length @ Unevaluated[spec] := 
  Which @@ MapAt[foo, Hold[spec], ;; ;; 2]

This way we will not evaluate foo with forms present after the correct one.

switch[True & @* Echo, a, 1, b, 2, c, 3]

>> a


  • $\begingroup$ Thanks, with SetAttributes[switch,HoldAll] if we want it to behave as Which right? (Otherwise the forms are already evaluated before they are taken as input.) $\endgroup$ – Kvothe Nov 5 '18 at 9:41
  • $\begingroup$ @Kvothe correct, I didn't do this because I was not sure if holding them makes sense, but now I think it does. See the edit. I've also included arg length check. $\endgroup$ – Kuba Nov 5 '18 at 12:46

Maybe this?

switch[f_, forms_, values_] := Which @@ Riffle[f /@ forms, values]

Usage example:

switch[# == "c" &, {"a", "b", "c", "d", "e"}, {1, 2, 3, 4, 5}]

However, this evaluates f over all forms , although it could also short-circuit.


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.