olivarra1
olivarra1

Reputation: 3409

what are `switch` statements for?

Switch statements: I know what they do - I use them so many times, as per convention normally when I want to do different stuff based on the value of an Enum, but now it just hit me: Why are we using it? What was its original purpose? I mean, this:

switch(myVar) {
    case Foo:
        doSomething();
        break;
    case Bar:
        doSomethingElse();
        break;
    default:
        justAnotherThing();
        break;
}

Has the exact same behaviour as:

if(myVar == Foo) {
    doSomething()
}else if(myVar == Bar) {
    doSomethingElse();
}else {
    justAnotherThing();
}

Plus if's lets you make inequality comparisons (>, <, !=) if you need it. The only case that I may find a switch more useful is when you don't use the break statement inside: but this happens not too often and I find it terrible on code-quality.

I really can't find any benefit of using switch over if... So why was it defined for?

Upvotes: 1

Views: 80

Answers (2)

Joey
Joey

Reputation: 354734

Some languages allow inequality comparisons in switch statements as well, e.g. Visual Basic:

Select Case x
  Case < 5
    // ...
  Case 7
    // ...
  Case 10 To 15
    // ...
  Case Else
    // ...
End Select

Basically, yes, the switch can often be written as an if/else if ladder, with the distinction that switch compares one value against a number of comparison values, if/else if can do anything in every single branch. But even that isn't the case in all languages, e.g. in PowerShell a switch can do plenty of things that you usually have to use if for:

switch -Regex ($x) {
  '^\d+$' {'Number'}
}

or

switch ($x) {
  { $_ is [int] -or $_ is [double] } {'Number'}
  { $_ is [string] } {'Text'}
}

Generally, however, switch is easier to read for the common case of comparing a single value against a finite set of options. Furthermore, it enables the compiler to do certain optimizations which are harder to analyse on if/else if, such as using binary search to determine the correct case instead of linear search, or even using a jump table or arithmetic. E.g. the following switch

switch (x) {
  case 0:
    // Do something with 0
    break;
  case 1:
    // Do something with 1
    break;
  case 2:
    // Do something with 2
    break;
  ...
}

could be compiled into the equivalent of

Action[] actions = {
  () => { /* Do something with 0 */ },
  () => { /* Do something with 1 */ },
  () => { /* Do something with 2 */ },
  ...
};
if (x >=0 && x <= n) {
  actions[x]();
}

The simplicity and limitations of switch are helpful in this case for an optimizing compiler because there's much less to analyse to determine what the overall structure is trying to do.

There are other features (sometimes maybe of dubious value), such as Duff's device, or being able to fall through to other cases (or goto arbitrary other cases, which, e.g. C# allows).

You may just as well ask the question why we have if statements and loops instead of just using goto. Yes, structured programming constructs are, taken one by one, strictly inferior in what they can express, compared to the more general construct. But they are more readable, make the intent clearer, and tend to be safer and easier to maintain.

Upvotes: 4

deceze
deceze

Reputation: 522470

switch is a pretty low-level statement, in the sense that the code in the case statements is compiled into a continuous block of instructions in memory which is simply conditionally jumped into (depends on the language in question of course, modern high-level languages may behave quite different under the hood). That's also why you have the fall-through behaviour, once a starting address is determined simply all following instructions are executed unless broken out of.

So initially it was a very natural way to jump over or into a block of instructions. Many languages have adopted the switch statement, many likely due to familiarity, but many likely also because it is indeed rather readable for certain cases, e.g.:

switch (someComplicatedCalculation($foo, $bar)) {
    case CONSTANT_A:
        ...
    case CONSTANT_B:
        ...
    ...
}

That's a pretty succinct way to express this, especially if you're maybe also depending on the fall-through behaviour.

Of course, other languages have never adopted switch, e.g. Python, and require the use of if..elif..else instead. In the end you can write similar code using either language construct, it's up to you.

Upvotes: 2

Related Questions