DEV Community

Meghan (she/her)
Meghan (she/her)

Posted on

Language Proposal: The 'Any' Switch Case

This feature proposal is language agnostic, as I have not seen this in any language before. If you know of an existing better way to do this, please let me know :)

The tagline for this feature is like if switch had a finally block, but only ran if the successful case found was not default.

Here's what it would look like in code:

switch (number) {
  case 1:
    ...
  case 2:
    ...
  case 3:
    ...
  any:
    ...
  default:
    ...
}
Enter fullscreen mode Exit fullscreen mode

The any block would be ran in this case if and only if case 1, 2, or 3 were also caught.

As far as whether or not the block would be run before or after the given case block is up to debate, and I could see scenarios where either would be useful. So it would be ideal to allow both, but I don't have a clear idea on how you could separate the difference between a before any clause and an after any clause.

Something I've been pondering the past few days. Feedback welcome! πŸ˜ƒ

Top comments (8)

Collapse
 
_bigblind profile image
Frederik πŸ‘¨β€πŸ’»βž‘οΈπŸŒ Creemers • Edited

Code is read much more often than it is written, and we understand code best when it executes the way we read it: top to bottom. We get into trouble when the flow jumps around. This is what makes asynchronous code so hard to understand without async/await.

Take this code block for example:

first();
setTimeout(function(){
    third();
}, 0);
second();

Here, the name of the functions I'm calling indicates in what order they're called, and there's this annoying jump.

So I think that even though


switch (a)  {
    case 1:
        doOne();
        doCommon();
        break;
    case 2:
        doTwo();
        doCommon();
        break;
    ...
}

Having this common code in each case might be a little bit longer, but when reading it, it takes a little less overhead. If the common code between cases spans so many lines that it's annoying to update everywhere, maybe you should put it into a function.

Collapse
 
nektro profile image
Meghan (she/her)

Readability is absolutely, and even I had some concerns about readability before I made the post. While the idea was drawn to me because I was thinking about the amount of cases there may be, so it would be more than a few lines, the particular piece of code that drew me to this, also may be able to be reworked to not use a switch at all and achieve the functionality I was hoping for.

Collapse
 
ryanberger profile image
Ryan Berger

So I've thought over this a couple of times, and I may not see the beauty of it, or am missing the benefits, but why couldn't you just put the line of code you want to run either before or after the switch? For example:

You propose:

const myValue = 10;
switch (myValue) {
    case 10:
        doThingForValue10();
        break;
    case 5:
        doThingForValue5();
        break;
    any: // maybe some sort of syntactic sugar to make block run before/after cases are evaluated:
        console.log(myValue);
        console.log("run for all cases");
}

However, this begs the question of when the any block actually runs. There can be lots of discussion on how we should achieve that, but I think it gets messy especially when you want some code to run before AND after. I think that you can write code with the same functionality in vanilla javascript which would look like this:

const myValue = 10;
console.log(myValue); // this would run just the same as it would inside the any block
switch (myValue) {
    case 10:
        doThingForValue10();
        break;
    case 5:
        doThingForValue5();
        break;
}
console.log("run for all cases"); // not only can we choose if it runs before/after, but we can split code that would be inside the any block to run before AND after
Collapse
 
megazear7 profile image
megazear7 • Edited

What about simplifying this:

switch (number) {

  any: // Runs before any matched case

  case 1: // ...

  case 2: // ...

  any: // Runs only after case 1 or 2 match

  case 3: // ...

  case 4: // ...

  any: // Runs after any of the previously matches cases

  default: // ...

}
Collapse
 
nektro profile image
Meghan (she/her)

Ooo, I like this! I thought about putting it before and after, and I love the addition of the middle block. But I worried about the readability of this. Since it begs the question, at least at this stage, does the middle bottom any run after 1,2,3,4 or just cover 3,4?

Collapse
 
megazear7 profile image
megazear7

I think it would just have to just be specified by the language. I'm not coming up with anything that wouldn't add a bunch of lexical complexity.

This does remind me though, when you have increasingly complex relationships between data and behavior, at some point it's best to abstract that into it's own class that can encapsulate that logic so that the language doesn't have to make increasingly strong opinions on how those relationships are expressed.

Collapse
 
rhymes profile image
rhymes

I have the feeling it'd complicate things for the reader while effectively saving only a few lines. What if suddenly you need to change the order in which operations are run but only for one case?

But it's also similar to a finally construct for exception handling. It might make sense in that regard

Collapse
 
awwsmm profile image
Andrew (he/him) • Edited

What about a template case?

switch (number) {

  template:
      before: // do something before
       after: // do something after

  case 1: // ...

  template case 2: // ...

  template case 3: // ...

  case 4: // ...

  default: // ...

}

template could be applied to only a particular subset of cases, and the template definition could be extended to do exception handling, etc.