神刀安全网

Making “switch” Cool Again

Making “switch” Cool Again

The switch statement is seldom used in most applications, but appears in almost all programming languages. I believe this is because switch is only useful in a very specific case. Thankfully, Go took a step back and said "we don’t have to do it the way everyone is used to" and rethought what it means to handle lots of branches of the same decision point without resulting to a chain of if statements.

The "break" Killed the "switch"

Consider the simplest and most obvious use of a switch in C++. Most languages that implement switch will use a similar syntax:

int dayOfTheWeek = 3; char *dayName = null;  switch (dayOfTheWeek) {     case 1:         dayName = "Monday";         break;     case 2:         dayName = "Tuesday";         break;     case 3:         dayName = "Wednesday";         break;     case 4:         dayName = "Thursday";         break;     case 5:         dayName = "Friday";         break;     case 6:         dayName = "Saturday";         break;     case 7:         dayName = "Sunday";         break; }

I realise this could be reduced to an array; just pretend these are more random values if you wish. This is already long and cumbersome, however it is slightly neater but longer than the alternative with chained if else statements:

int dayOfTheWeek = 3; char *dayName = null;  if (dayOfTheWeek == 1) {     dayName = "Monday"; } else if (dayOfTheWeek == 2) {     dayName = "Tuesday"; } else if (dayOfTheWeek == 3) {     dayName = "Wednesday"; } else if (dayOfTheWeek == 4) {     dayName = "Thursday"; } else if (dayOfTheWeek == 5) {     dayName = "Friday"; } else if (dayOfTheWeek == 6) {     dayName = "Saturday"; } else if (dayOfTheWeek == 7) {     dayName = "Sunday"; }

To me this is very ugly, repeats a lot of code and is less explicit than the switch version, but since it’s shorter and more flexible it’s usually the preferred option. Now let’s see how Go handles it:

dayOfTheWeek := 3 var dayName string  switch dayOfTheWeek {     case 1:         dayName = "Monday"     case 2:         dayName = "Tuesday"     case 3:         dayName = "Wednesday"     case 4:         dayName = "Thursday"     case 5:         dayName = "Friday"     case 6:         dayName = "Saturday"     case 7:         dayName = "Sunday" }

Yes! Now we get to the crux of it. The break statement is the wart that has killed the beautiful simplicity of the switch . It should have been original designed with the intention that in the vast majority of cases you will only want one case to match and not have to pollute your source with break statements.

Collapsing Cases

Since the normal implementation relies on the break to not fall through; several cases can grouped. Go takes it one step further by comma separating all the matching values. This is less typing and even more explicit:

dayOfTheWeek := 3 var dayName string  switch dayOfTheWeek {     case 1, 2, 3, 4, 5:         dayName = "Weekday"     case 6, 7:         dayName = "Weekend" }

Expressions

The other reason why switch is seldom used is because in many languages the value that it’s switching on must by a primitive, sometimes even restricted to an integer. Go removed this limitation as well by allowing complete expressions for cases:

switch {     case dayOfTheWeek <= 5:         dayName = "Weekday"     case dayOfTheWeek > 5:         dayName = "Weekend" }

If you use expressions for cases you do not need to even specify a switch value. This works more like a chained if statement. Furthermore, Go’s ability to declare scoped variables makes this switch even more readable:

dayOfTheWeek := 3 var dayName string  switch friday := 5; true {     case dayOfTheWeek <= friday:         dayName = "Weekday"     case dayOfTheWeek > friday:         dayName = "Weekend" }

Empty Cases

Empty cases mean it does nothing :

switch hasHadCoffee {     case false:         // Don't talk to me.     case true:         readyToTalk() }

Falling Through

If traditional switches rely on break statements to not fall through, then fallthrough would be the opposite. A case never falls through unless you have an explicit fallthrough :

count := 0  switch {     default:         count++         fallthrough     case false:         count++ }

It’s important to recognise that count is 2 because fallthrough will always run the next case, even if it wouldn’t normally be hit.

Type Switching

One great thing about Go is that type casting and assertions can be put into the same line:

var value interface{} = "hello" if str, ok := value.(string); ok {     // str must be a string } else {     // error handling }

If there are more than one possible expected type you can do the same thing with a switch :

var value interface{} = "hello" switch o := value.(type) {     case string:         // o is a string     case int:         // o is an int     default:         // Handle the unknown type         panic(o) }

Conclusion

Go not only makes switch useful, it reinvigorates and promotes it to a powerful and flexible tool. I believe similar functionality could be implemented in other languages by using functions and arrays… Maybe a side project there.

Please leave your comments below. Happy coding.

You might also be interested in these articles…

Elliot Chance –

I’m a data nerd and TDD enthusiast living in Sydney, Australia. I love exploring new technologies and working on modern ways to solve age old problems.

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Making “switch” Cool Again

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
分享按钮