2

In JavaScript, I am trying to write a switch statement that does something like the following -

swtich(n)
{
   case 1:
      functionW(); functionX(); functionY(); functionZ();
      break;
   case 2:
      functionX(); functionY(); functionZ();
      break;
   case 3:
      functionY(); functionZ();
      break;
   default:
      functionZ();
      break;
}

Is there a better way to do this?

A Bogus
  • 3,852
  • 11
  • 39
  • 58

4 Answers4

2

Frits van Campen's answer is the closes to the same exact functionality you described. I always have bugs when I use switch with/without fallthrough. If n is a number I'd use:

if(n >= 1){functionW();}
if(n >= 2){functionX();}
if(n >= 3){functionY();}
functionZ();

(I removed my second answer as Barmar expressed it better.)

Edit:

It can be modified to work with non-numbers:

var test = false
if(n === 1 || test){test = true; functionW();}
if(n === 2 || test){test = true; functionX();}
if(n === 3 || test){test = true; functionY();}
functionZ();
Jacob
  • 1,423
  • 16
  • 29
  • Your first option is by far the best among the presented here: it clearly states the intent/condition of each function. – acdcjunior Jun 26 '13 at 17:04
  • And this assumes the values to switch against are always `Number`s (for the first example) – Ian Jun 26 '13 at 17:05
  • @lan they are numbers in the original code. I see no problem - other than the order and he has the same problem with the dispatch table that I mentioned in Barmar's answer. – Halcyon Jun 26 '13 at 17:06
  • 1
    @FritsvanCampen I understand, but this is a very generic question...note the `functionW`, `functionX`, etc. names. I can't expect the values to always be numbers. The fact that they're using a `switch` means they're doing an equality comparison, not with `<`, even if it satisfies the only example – Ian Jun 26 '13 at 17:07
  • Yea I suppose you're right. If you don't have ordinality in your cases you couldn't use this `if` structure. – Halcyon Jun 26 '13 at 17:08
  • @FritsvanCampen I know I'm being real technical, I'm not trying to be annoying, I'm just trying to think of a generic answer – Ian Jun 26 '13 at 17:09
  • Your comment is valid, it's always good to look at the big picture :) – Halcyon Jun 26 '13 at 17:10
  • @Jacob Also, you shouldn't declare a variable as `function` - it' a reserved word, and will throw a syntax error – Ian Jun 26 '13 at 17:10
0

Remove the break

The cases will fallthrough.

Make sure you explicitly note that you don't want to break because it may look like a bug.

switch(n)
{
   case 1:
      functionW();
      // dont break
   case 2:
      functionX();
      // dont break
   case 3:
      functionY();
      // dont break
   default:
      functionZ();
      // dont break
}

If n is 1 it will execute functionW() then fallthrough to case 2 and execute functionX(); and so on...

Halcyon
  • 57,230
  • 10
  • 89
  • 128
  • I'm not sure I would've thought of this, pretty cool. Not sure why this was downvoted either – Ian Jun 26 '13 at 16:52
  • 1
    @Ian because its brittle and is considered a bad practice. Also, there is often a much more clean way to do it. See longer discussions: [here](http://stackoverflow.com/questions/188461/switch-statement-fallthrough-should-it-be-allowed) and [nearby](http://programmers.stackexchange.com/questions/116221/appropriate-uses-of-fall-through-switch-statements) – c69 Jun 26 '13 at 16:56
  • 1
    Some IDEs (e.g. PhpStorm/IDEAJ) will warn about switch without `break`. Is there a doc-comment way to tell them that it's OK? – Barmar Jun 26 '13 at 16:56
  • @c69 If you think there is a cleaner way you're welcome to post your own answer. I'm excited to see what you come up with. – Halcyon Jun 26 '13 at 17:00
  • 1
    @c69 Hmm I never knew it was considered a bad practice, but then again I've never really needed to use `switch` statements or cared to look into that, but your links clearly show that's true. I understand it can be error-prone and isn't as readable, but I feel like one should learn the tools you use before using them - it might just be me, but it seems plenty fine to use fallthrough here, probably because I'm not a newbie (which you mentioned). What would you suggest, `if` statements then? – Ian Jun 26 '13 at 17:00
  • 1
    I can't think of a cleaner way other than a bunch of `if`s – Ronnie Jun 26 '13 at 17:01
  • @FritsvanCampen in this case, Jacob gave the most explicit solution (group of `if`'s without else). But often in JS you can wrap `case` items into functions, so you will just call `action[2]()` or `action[name]()`. For other languages, or things like parsers, or contests (when the code length might matter) - switch is perfectly valid, and fallthrough is a tolerable hack. In short: your answer is correct, but hopefully the vocal -1 and the chain of comments will force the readers and googlers to think before using it. – c69 Jun 26 '13 at 17:35
0

Instead of a switch, consider iterating through a dispatch table:

var functions = [ functionW, functionX, functionY, functionZ ];
for (i = n; i < functions.length; i++) {
    functions[i]();
}

In this case, n should start with 0 rather than 1. And if functionZ() is really for all values higher than 3, you can cap n at the beginning of the loop:

for (i = (n >= functions.length ? functions.length-1 : n); i < functions.length; i++) {
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • I think you should not put `functionZ` in the dispatch table, call it after the `for` loop instead. It depends on possible values of `n` though, if `n` can be 5 this code is not equivalent. – Halcyon Jun 26 '13 at 17:04
  • You can cap `n` before the loop if necessary. – Barmar Jun 26 '13 at 17:05
  • But you need to make sure `functionZ` _always_ gets called. – Halcyon Jun 26 '13 at 17:07
0

I just thought of a different solution.

Write your functions like this:

function functionW() {
    // do stuff
    functionX();
}

function functionX() {
    // do stuff
    functionY();
}

// etc

Then you don't need a fallthrough, you can have one switch case with breaks.

Just because you defined your functions like functionW, functionX etc. and you need to call them in that way doesn't mean your function composition is necessarily good.

Halcyon
  • 57,230
  • 10
  • 89
  • 128