Thoughts on switchs.

Started by
9 comments, last by Khatharr 11 years, 4 months ago

so, i was thinking of switch's the other night, and one of the annoyances i find with switchs is that in many cases, i simply write out code that boils down to being an if/else if/else statement's because all the switch wants to do is break out after each case, and I only potentially want to use w/e the compiler optimizations switchs with. so i was thinking of a potential design solution for this, that doesn't require adding a break after every statement, and came up with this:


int Foo(int value){
 int r=0;
 switch(Value; break){ //think of w/e is after the ; as a goto at the bottom of each case, so with this one statement, i append a break to every single case, this could be used for anything, but break is just a common example.
  case 0: r=1;
  case 1(): r=2;//appending a () before the : and after the value overrides what the switch statement's conditional does, with what is specefied in the (), in this case, nothing is specefied, so we have default switch behavior here.
  case 2: r=r+2;
  default: r=100;
}
return r; //I know i can just return in the switch to do what i want, but this is suppose to be an example.
}
 
int main(int argc, char **argv){
 Foo(0) //R = 1
 Foo(1) //R = 4
 Foo(2) //R = 2
 Foo(3) //R = 100
 return 0;
}

any thoughts on this, is their a more elegant design that i'm missing, or are my thoughts on this just crazy/stupid?

and yes, their is plenty of room for discussion on why one would design code that essentially boils down to an if/else if/else code block, and i suspect that this discussion might fall into that, but we'll see what people's thoughts on this is.

Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.
Advertisement

Are you designing a new language or something? I am used to the current behavior of switch in C/C++, and I don't feel the need for any extensions.

The larger problem with switch cases is that they are frequently used in inappropriate situations. If you find yourself writing switch cases that boil down to if/else constructs frequently then you are likely to be approaching the problem the wrong way anyway.
Even in the example you gave the correct solution would actually be:


static int iTable[] = {
	1,
	4,
	2,
};
return iValue < (sizeof( iTable ) / sizeof( iTable[0] )) ? iTable[iValue] : 100;

The only time switch cases should ever be used is when the logic between each possible case actually changes, but sadly most people do not restrict their switch cases to just these situations and that ends up making switch itself seem like the actual problem.

The problem with the solution you proposed is that it makes it very hard to follow the logic of the switch case. It becomes very easy for others reading your code to miss when it will fall through etc.

I would say the best solution is to keep the syntax as it is for clarity but to seek more elegant solutions, since there very frequently are some.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

I agree to avoid switch in most situations. I often write things like this:
#include <unordered_map>

int Foo(int value) {
  static std::unordered_map<int, int> const map = {{0,1}, {1,4}, {2,2}};

  auto it = map.find(value);
  return it == map.end() ? 100 : it->second;
}
Are you designing a new language or something? I am used to the current behavior of switch in C/C++, and I don't feel the need for any extensions.

no, not at all, this is just something that's been on my mind the last couple of days, and was curious for hearing the thoughts of others.

The larger problem with switch cases is that they are frequently used in inappropriate situations. If you find yourself writing switch cases that boil down to if/else constructs frequently then you are likely to be approaching the problem the wrong way anyway.
Even in the example you gave the correct solution would actually be:

static int iTable[] = {
	1,
	4,
	2,
};
return iValue < (sizeof( iTable ) / sizeof( iTable[0] )) ? iTable[iValue] : 100;

The only time switch cases should ever be used is when the logic between each possible case actually changes, but sadly most people do not restrict their switch cases to just these situations and that ends up making switch itself seem like the actual problem.

The problem with the solution you proposed is that it makes it very hard to follow the logic of the switch case. It becomes very easy for others reading your code to miss when it will fall through etc.

I would say the best solution is to keep the syntax as it is for clarity but to seek more elegant solutions, since there very frequently are some.

L. Spiro

I completely agree that their are better solutions(and the one you present is a very good solution to the problem presented above). I also agree that the above idea could cause missed interpretation of what's going on, but it would be something people would learn to look for after the first few mistakes(at least imo.)

Personally, i had been told by fellow programmers that using a switch is a good idea when you are only selecting an option, but the code created is pretty ugly imo(alot of needless whitespace) while i know programming isn't exactly about how the program is laid out, but how it functions, it still shy's me away from using switchs for this reason.

Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.
Reacting with different logic to enum values maybe.

If your switches start to get ugly you can use inline functions to encapsulate the blocks.

My winprocs often end up with each line looking something like:

case LABEL: labelProc(); break;

This ends up looking far more managable than the normal "uberfunction" I used to hate so much.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

I agree for the most part that switch should be avoided when possible, though it does have it's uses. I do not however miss it when programming in languages that don't support it, such as Python.

I also advocate against overloading core functionality that does not contextually make sense. Most people don't like being surprised by such things, and I wouldn't even recommend it if you are the sole developer.

You don't like debugging?
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.
SPECS has an interesting take on switch. It allowed multiple numbers to be attached to a single case, required a block to follow each case and instead of using break to prevent fall through, you used continue to force fall through.
My winprocs often end up with each line looking something like:

case LABEL: labelProc(); break;

If you are going to do that, you may as well just have a container of pointers to function, or a container of std::function, or a container of signals (like boost::signal). You just "register" in that container any behavior you need to have in response to events, and then the function itself is very clean. I have done this type of thing before around select() for network programming in Unix, and it works great.

This topic is closed to new replies.

Advertisement