There are changes to switch statements that would make my life much easier. They are perhaps best explained by just showing you how I want them to work.
switch ($somevar as $s) { case 0: if (do_something()) { $s = 1; continue; } break; case 1: $var = "Something"; continue; case 2: $var = "Some "; case 3: $var .= "Things"; continue; case $s > 4: $var = "Too Much!"; case $s > 0: echo $var; break; default: throw new Exception('$somevar cannot be less than 0'); break; }
To visualize how this would work, let's show what the output should be for a few values of $somevar:
$somevar = -1; // Exception $somevar = 0; // do_something() called - if it returns true, echo "Something" $somevar = 1; // echo "Something" $somevar = 2; // echo "Some Things" $somevar = 3; // echo "Things" $somevar = 4; // echo "Too Much!" $somevar = 5; // echo "Too Much!"
So what's going on here? Well there are two changes to the syntax of the switch statement that I'm proposing.
continue;' breaks out of flow-through, and continues to evaluate cases.as $s' provides a simple variable that can be used for comparison in case statements.Let's tackle them one at a time then:
Using 'continue;' to break out of flow-through
The way switch statements work is that once you trigger one case, that's it; you're going to run every following case until you hit 'break;' or run out of cases. This is known as flow-through, and can be very useful for dealing with multiple cases slightly differently. The problem is that it's only useful if you can logically order your cases to make use of it. If you have a few different cases that you may want to trigger, but you don't want to trigger all of them, then you'll either have to put it in a loop (making sure to change the item being checked so you don't just trigger the same cases each time), nest if/switch statements (and have redundant, repeated code), or wrap the common code in a function (and have to look for the function to follow the code flow). As you can tell, I think these are all bad solutions.
If you could 'continue' instead of 'break', you could stop the flow-through and evaluate each following case so that you're only triggering the ones you want. This would give you more control over the flow of your program.
Using 'as $s' to provide a locally scoped variable for comparison
In this instance, '$s' would become a variable scoped locally to the switch statement, which can be read, changed, or compared to affect the matches without affecting the original variable. This could easily be done by assigning the value that you're checking to a new variable before the switch statement, and destroying it afterwards, but that is more code and could lead to many strange bugs. The idea is that the variable is generated once, and then is scoped locally and used for matching each case.
Combined with the 'continue' statement, it means that you could effectively trigger different statements in a row, as required. The other advantage is that because the variable is scoped locally to the switch statement, if you jump outside the statement (or an exception is triggered, etc.), then the variable will be properly disposed of and won't continue living in a wider scope.
Effect on existing code
Implementing these changes could break some existing code, as 'continue' only had meaning in the context of loops (although 'break' had meaning in the context of both loops and switch statements). This meant that it was possible to use 'continue' inside a switch statement to refer to an outer loop. Solutions to this would be to either pick another keyword, or to allow syntax like 'continue 2;' to refer to the outside loop. The latter would be more consistent with the existing behaviour of 'break', but would still make a large amount of existing code behave differently. Implementing 'as $s' should have no affect on existing code.
So what would it take to implement these?
Right now, I don't know. People will probably tell me that these ideas are as bad as GOTOs, or that the way that switch statements are implemented as jump tables would be incompatible with implementation. This is something that I could make use of in several languages, but would probably just add to the confusion surrounding an already much misunderstood statement.
Let me know what you think, and maybe we'll see something like this implemented in the future.
Comments
Almost but not quite what you want
You can do something similar using this peculiar syntax:
For some situations, I like this better - especially when switching based on conditions involving multiple different variables, because the conditions in each case-statement are complete: you don't have to look back up to see what you were switching against.
Also check out the incredible switch-statement in Opa - rather dreamy :-)
Post new comment