9

Will the default of a switch statement get evaluated if there's a matching case before it?

ex:

switch ($x) {
  case ($x > 5): print "foo";
  case ($x%2 == 0): print "bar";
  default: print "nope";
}

so for x = 50, you'd see foo and bar, or foo and bar and nope?

beth
  • 1,916
  • 4
  • 23
  • 39

4 Answers4

9

Yes, if there is no "break", then all actions following the first case matched will be executed. The control flow will "falls through" all subsequent case, and execute all of the actions under each subsequent case, until a break; statement is encountered, or until the end of the switch statement is reached.

In your example, if $x has a value of 50, you would actually see "nope".

Note that switch is actually performing a simple equality test, between the expression following the switch keyword, and each expression following the case keyword.

Your example is unusual, in that it will only display "foo" when $x has a value of 0. (Actually, when $x has a value of 0, what you would see would be "foo bar nope".)

The expression following the case keyword is evaluated, which in your case, example return a 0 (if the conditional test is false) or a 1 (if the conditional test is true). And it's that value (0 or 1) that switch will compare to $x.

spencer7593
  • 106,611
  • 15
  • 112
  • 140
6

Will the default of a switch statement get evaluated if there's a matching case before it?

In most cases it shouldn't, because you would often have breaks in there. However in your case it would also go to the default.

Also please try to prevent to do those single line stuff (for readability):

$x = 10;

switch (true) {
  case ($x > 5):
      print "foo";

  case ($x%2 == 0):
      print "bar";

  default:
      print "nope";
}

Will print foobarnope. So to answer your question: yep :-)

PeeHaa
  • 71,436
  • 58
  • 190
  • 262
  • prints `foobarnope`. Soon as any case is true, all following cases, including default, up to a break (or end of switch) will run. http://codepad.viper-7.com/sjHYeZ – Jonathan Kuhn Aug 10 '12 at 15:25
3

That's not how switches work.

According to the manual:

The switch statement is similar to a series of IF statements on the same expression. In many occasions, you may want to compare the same variable (or expression) with many different values, and execute a different piece of code depending on which value it equals to. This is exactly what the switch statement is for.

An evaluation like

case ($x > 5):

simply equates to

case true:

or

case false:

depending on the value of $x because ($x > 5) is an EVALUATION, not a VALUE. Switches compare the value of the parameter to see if it equates to any of the cases.

switch($x) {
    case ($x > 5): // $x == ($x > 5)
        echo "foo";
        break;
    case ($x <= 5): // $x == ($x <= 5)
        echo "bar"
        break;
    default:
        echo "default";
        break;
}

The comparison in the above code is equivalent to

if ($x == ($x > 5)) {
    echo "foo";
} elseif ($x == ($x < 5)) {
    echo "bar";
} else {
    echo "five";
}

which (when $x == 50) is equivalent to

if ($x == true) {
    echo "foo";
} elseif ($x == false) {
    echo "bar";
} else {
    echo "five";
}

which is equivalent to

if (true) { // $x == true is the same as saying "$x is truthy"
    echo "foo";
} elseif (false) {
    echo "bar";
} else {
    echo "five";
}

IF, however, you used your switch statement as it is intended to be used (to compare the parameter to concrete values):

switch ($x) {
    case 50:
        echo "foo ";
    case 30:
        echo "bar ";
    default:
        echo "foo-bar";
}

and $x == 50, your output would be

foo bar foo-bar

due to the fact that you have no break in your cases.

Had you added the break keyword to the end of each case, you would only execute the code for that specific case.

switch ($x) {
    case 50:
        echo "foo ";
        break;
    case 30:
        echo "bar ";
        break;
    default:
        echo "foo-bar";
        break;
}

Output:

foo 
Matt
  • 6,993
  • 4
  • 29
  • 50
  • 4
    No, you didn't. Read what you wrote. You said that you **can't** use switches "like that", and you are wrong - you can, and nothing prevents anyone from doing so. Posting a half-correct answer is horrible, someone will walk in and read what you wrote and think you were right when you weren't. – N.B. Aug 10 '12 at 15:00
  • 3
    The OP's switch statement perfectly valid. Having evaluations in cases is perfectly valid and highly desirable code. Your answer only shows one type of use of the statement. – Buggabill Aug 10 '12 at 15:02
  • 1
    @Matt - there's nothing wrong behind the logic you're trying to explain, what's wrong is your explanation of the `switch` statement. Switch statement behaves exactly like an `if` statement. You can compare values in order to get a `true` or `false`. `switch` is just a convenience invented so one doesn't have to type 100 if/else combinations and nest the code to oblivion. – N.B. Aug 10 '12 at 15:04
  • @buggabill I'm not so sure it's *highly desirable* but it is valid. My point was that it shouldn't be used in that fashion **unless it's fully understood why it's being used.** – Matt Aug 10 '12 at 15:05
  • @N.B. So are you saying that `case ($x > 5)` is the same as `if ($x > 5)`? Because it isn't. It equates to `if ($x == ($x > 5))` and OP needs to know that. – Matt Aug 10 '12 at 15:06
  • @Matt - well, I'm sorry but you're wrong. A `switch` statement behaves exactly like an `if`. `case $x > 50:` is exactly like `if($x > 50)` and that's that. – N.B. Aug 10 '12 at 15:09
  • @N.B. my answer was in response to OP's final question: `so for x = 50, you'd see foo and bar, or foo and bar and nope?` Clearly, she doesn't understand how comparisons are done in a `switch` and I'm pretty sure this answer helped clarify that. – Matt Aug 10 '12 at 15:10
  • @N.B. [Show me in the documentation where a `switch` behaves like that and I'll give you a free 500 point bounty.](http://php.net/manual/en/control-structures.switch.php) – Matt Aug 10 '12 at 15:12
  • @N.B. *"The switch statement is similar to a series of IF statements on the same expression. In many occasions, you may want to compare the same variable (or expression) with many different values, and execute a different piece of code depending on which value it equals to. This is exactly what the switch statement is for."* – Matt Aug 10 '12 at 15:15
  • @N.B. http://stackoverflow.com/questions/11904754/switch-evaluations Hopefully the answer to this question will settle this argument of ours. If I'm wrong, I'll remove my answer and award you 500 bounty. If I'm correct, I expect you to remove your comments and your -1. – Matt Aug 10 '12 at 15:32
  • @N.B., @Matt is exactly right about how the switch works. if you had a switch of `switch($x){ case 0: echo "hi"; break; }` wouldn't the equivalent if statement be `if($x == 0)...`? so then why wouldn't the OP's switch not be equal to `if($x == ($x > 5))...`? do you somehow lose the case equation? – Jonathan Kuhn Aug 10 '12 at 15:43
  • 2
    @Matt, one line though I don't agree with. "The output for the above code would always be default unless $x == 1". This untrue. In the comparison `$x==($x > 5)` for example, there is an implicit conversion of $x to boolean which will evaluate to true as long as $x!=0. If `$x=0`, that statement will actual return true as $x will be false and $x>5 is false so you get `false==false`. If $x=1 to 5, the statement returns false as any non 0 number converts to boolean true. so the statement becomes `true==false`. any number above 5 the statement will return true `true == true`. – Jonathan Kuhn Aug 10 '12 at 16:00
2

It would have been easier to try it yourself.

But anyway, if you don't use break in a case, all the the cases following it will be executed (including the default).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Oussama Jilal
  • 7,669
  • 2
  • 30
  • 53
  • It's true that there are places other than stackoverflow to figure out the answers to questions, but when we do that no one gets to collect rep ;-) – beth Aug 10 '12 at 14:52