# Fall through multiple statements in Switch[]

Is there a nice way in Mathematica to express the equivalent of Switch where statements (not cases) fall through? Here is a toy example in C:

switch (n)
{
case 4: printf ("4");
/* fall through */
case 3: printf ("3");
/* fall through */
case 2: printf ("2");
/* fall through */
case 1: printf ("1");
break;
}


(In reality the statements would be computations, not just printf's.)

I've thought of two ways. One is to use Goto[] and Label[]:

ClearAll[trial1];

trial1[n_] := Module[
{one, two, three, four},
Goto[{one, two, three, four}[[n]]];

Label[four];
Print[4];

Label[three];
Print[3];

Label[two];
Print[2];

Label[one];
Print[1];
]


The other holds each statement in a list, takes the desired elements, and releases the holds:

ClearAll[trial2];

trial2[n_] := Module[
{lst},
lst = {
Hold[Print[4];],
Hold[Print[3];],
Hold[Print[2];],
Hold[Print[1];]
};
ReleaseHold[Take[lst, -n]];
]


Both work, but neither seems "clean" or Mathematica-like.

My question differs from this one where several cases fall through to the same statement.

Added later: Here is a sample. Calling the function with 3 results in the last three statements executing.

trial2[3]


(* 3 2 1 *)

• Doesn't Which[ ] do what you are asking? Jan 19, 2022 at 22:00
• @BillS Documentation says that Which[] returns the value of the first test that evaluates True, not every subsequent value too. Jan 19, 2022 at 22:05

I recall once someone defending Mathematica's Switch[] not falling through, perhaps as less bug-prone as C's switch(). I can't recall what they recommended to do instead.

Here's a way to present the code blocks, even give them helpful names (other than "A", "B" etc. that I use below), and execute them conditionally in whatever order. While the C switch() is a perhaps a glorified assembly branch, this is basically an implementation of a C switch table (AFAIR) with a slight -- perhaps only very slight -- Mathematica flair. It also allows more general execution patterns than "fall-through," which was allowed in C because it was easy to implement in assembly language.

I took the OP's question to be general, not the specific, overly symmetric pattern in the example. That is, my solution may be applied to more complicated switch cases than a sequence of positive integers less than some value for n.

exec = <|   (* code texts *)
"A" :> Print["Code 1"],
"B" :> Print["Code 2"],
"C" :> Print["Code 3"],
"D" :> Print["Code 4"]|>;
switch = {  (* switch table with fall-through defined by lists *)
4 -> {"D", "C", "B", "A"}, (* keys to code texts to be executed *)
3 -> {"C", "B", "A"},
2 -> {"B", "A"},
1 -> {"A"},
_ :> Throw[$Failed]}; (* optional default *) nn = 4; Scan[exec, Replace[nn, switch], 1] (* Code 4 Code 3 Code 2 Code 1 *)  I think Scan and Replace are expressive of the intention. Replace will fail if nn does not have an appropriate value, even if there is no default case -- that is, it will leave nn unchanged if there is no default. ReplaceAll may be used instead -- the operator /. is convenient -- but it might replace parts of nn if it has integer parts. If bad input is a possibility, then Replace might be safer. nn = 3; Scan[exec, nn /. switch, 1] (* Code 3 Code 2 Code 1 *)  One reason for using a list instead of an association for the switch is that the keys can be patterns. This also shows that the order of the code texts can be arbitrary. switch2 = { 4 | 3 -> {"D", "C", "B"}, (* pattern key *) 2 -> {"B", "C"}, (* reversed order - can't be done in C *) 1 -> {"A"} _ :> Throw[$Failed]};     (* optional default *)
nn = 3;
Scan[exec, Replace[nn, switch2], 1]
(*
Code 4
Code 3
Code 2
*)


Here's the shortest way to type a workaround:

nn = 2;
nn /. switch2 /. exec
(*
Code 2
Code 3
Out[]= {Null, Null}
*)

• Another way to do the simpler example in the OP, bypassing the switch table: Scan[exec, Take[{"D", "C", "B", "A"}, -nn]] Jan 19, 2022 at 22:39

I think your trial2 gets pretty close. This seems more idiomatic:

SetAttributes[trial3, HoldRest];
trial3[n_, list_] := Take[Unevaluated@list, -n]

trial3[3, {Echo[4], Echo[3], Echo[2], Echo[1]}]

(* >> 3 *)
(* >> 2 *)
(* >> 1 *)
(* {3,2,1} *)


An answer subsequently deleted by @Nassar started me thinking about a function whose argument indicates which individual statement. That function can be invoked multiple times by Scan[]ing a list:

ClearAll[trial3];

trial3[n_] := Scan[
Switch[#,
1, Print["1"],
2, Print["2"],
3, Print["3"],
4, Print["4"]
] &,
Take[{4, 3, 2, 1}, -n]
]


I'm interested in other solutions.

We could implement that style of Switch with Label and Goto:

ClearAll[cSwitch];
SetAttributes[cSwitch, HoldAllComplete];

cSwitch::OddCases =
"cSwitch called with 1 arguments. cSwitch must be called with an odd number of arguments.";

cSwitch[value_, pairs__] :=
Module[{cases = HoldComplete[{pairs}], casesLength, begin, n = 1, matchFlag = False, lastValue},

casesLength = cases /. HoldComplete[a_] :> Length[Unevaluated[a]];

Block[{Break = Return},
If[OddQ[casesLength], Message[cSwitch::OddCases, casesLength + 1];
Return[Defer[cSwitch[value, pairs]]],

Label[begin];

If[matchFlag || MatchQ[value, Extract[cases, {1, n}, ReleaseHold]],
matchFlag = True; lastValue = Extract[cases, {1, n + 1}, ReleaseHold]];

If[n < casesLength - 1, n += 2; Goto[begin], Return[lastValue]];
]
]]


Use it as just like Switch. It will execute all the cells after it finds a successful match until Break[] was called or reach the end, like C/Java. Also, if you use Break[1], 1 will be returned (ignore the red color).

## Example

Consider this function:

ClearAll[dummyFn];
dummyFn[n_] :=
cSwitch[n, 1, Print[1]; 1,
2, Print[2],
3, Print[3]; Break[],
4, Print[4]; 4,
_, Print[Infinity]; -1
];


Test:

dummyFn[1]

(* Print 1 *)
(* Print 2 *)
(* Print 3 *)

(* Return Null *)

dummyFn[4]

(* Print 4 *)
(* Print Infinity *)

(* Return -1 *)

dummyFn[5]

(* Print Infinity *)

(* Return -1 *)


Thanks to @jojo for his answer in this post.