History of the horrid switch statement (iii): C and beyond

C is where the concept of a multi-way statement was to fall off the rails. Partially because the control structure is hard to teach to novice programmers, and lacks the elegance of what came before. Consider the structure of C’s  switch statement:

switch (n) {
    case C1 : S1;
    case C2 : S2;
    ...
    case Cn : Sn;
    default : Sd;
}

The problem with the C switch statement, is that it allows fall-through, only single case, i.e. no ranges are allowed, and only integers for comparison (which might have been derived from Algol 68, which only allowed integer expressions). Fall-through is a unique problem (and in some cases is useful), which means that if n=C2, then after performing S3, the program will proceed to perform S4, etc., and the only way around this fall-through is the use of the keyword break. This harkens back to the notion that C is assembly in disguise. Break acts like it a separator, but in reality is more of a goto, transferring control to the end of the statement. It also suffered from an inability to allow ranges of values. So one could end up writing a piece of code that looks like this:

switch (n) {
    case 1 : ;
    case 2 : ;
    case 3 : ;
    case 4 : x = x + 1; break;
    case 5 : x = x + 2;
}

Here if the value of n is 1, 2 or 3, it just falls through to the statement at n=4, effectively mimicking “case 1..4” . Messy right? (But I have seen code like this). Better to have used a if statement to begin with. Finally, if the program requires a series of statements under each case, then you have to use { }.

The multi-selection of Ada combines the best characteristics of both Algol 68, and Pascal:

case expr of
    when C1 => S1;
    when C2 => S2;
    ...
    when Cn => Sn;
    when others => Sm;
end case;

C1,…,Cn are possible values, for example:

1
3..10
11 | 14
2 | 20..30

The case statement in Ada is functionally identical to that of C, however, unlike C, Ada supports ranges of values, and does not require a break statement. Here’s an example:

case currentmonth is
    when May..Jul => prices := summerrates;
    when Aug|Sep|Feb..Apr => prices := standardrates;
    when Dec => prices := holidayrates;
    when other => prices := winterrates;
end case;

Which is quite elegant. Fortran 90 provided a selectcase structure, which was essentially a replacement for the computed goto:

select case (i)
    case (C1)
        S1
    case (C2)
        S2
    case default
        Sd
end select

Here C1 and C2 are selectors which can consist of a list and/or range of integers, character or logical constants. The switch statement in Swift is a derivative of that of C:

switch C {
    case P1 : S1;
    case P2 : S2;
    case P3 : S3;
    default : Sd;
}

The major difference is that in Swift case statements do not implicitly fall-through. Swift case statements can match multiple cases on the same line – each value is separated by a comma before the colon. Also it allows ranges (X…Y). Here’s an example:

switch X {
    case 0,2,4,6,8 : println(“even”)
    case 1,3,5,7,9 : println(“odd”)
    default : println(“NaN”)
}

Finally, an elegant fix to the limitations of C’s switch.

Note that neither Lua, nor Python, nor Julia have a case or switch equivalent.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s