switch() and default:

php.internals

Frank M. Kromann

21 years ago
Hello Everyone, I just discovered a small thing in the switch() statement. The position of the default: clause has to be at the end of the code: $a = 1; switch ($a) { default : case 0 : $b = 1; break; case 1 : $b = 2; break; } echo $b; // should print 2 but it prints 1 $a = 1; switch ($a) { case 1 : $b = 2; break; default : case 0 : $b = 1; break; } echo $b; // prints 2 as expected. This is tested on Linux with PHP5 CVS-HEAD What changed ? - Frank

Andi Gutmans

21 years ago
It's always been like that and has been documented for ages in the manual. Andi At 08:24 PM 10/7/2004 -0700, Frank M. Kromann wrote:

Benj Carson

21 years ago
Hi, Sorry, I forgot to CC my last reply to the list. I noticed similar behaviour and filed a bug report: 30285. The case described in the bug report is as follows: $x = "a"; switch ($x) { default: echo "default"; break; case "a": echo "a"; break; } // Prints "a" Even though the documentation mentions that default should always be last, this is a BC break from 5.0.x and at least 4.3.2. Thanks, Benj On October 7, 2004 10:59 pm, Andi Gutmans wrote:

Unnamed Person

21 years ago
prints "a" on 4.2.3 Novell, 4.3.3 Linux, 5.0.0 Windows. On Fri, October 8, 2004 12:21 am, Benj Carson said:

Ron Korving

21 years ago
No matter what behaviour PHP shows, I would find it bad coding if you place default anywhere but at the bottom, simply because you might run into unexpected behaviour in other versions of the PHP engine, which I assume you're experiencing now. You could've seen this coming. When you write a switch, think of it as the input being matched case by case, with "default" being the case that matches anything. This means you don't wanna place the default case anywhere but at the bottom. Ron "Benj Carson" <benjcarson@digitaljunkies.ca> wrote in message news:200410072321.19072.benjcarson@digitaljunkies.ca...

Benj Carson

21 years ago
Coming from C (or Java), I find the new behaviour a little strange. If you use default to match invalid conditions, putting it at the beginning of a switch doesn't seem to be poor practice to me (putting it in the middle would be pretty ugly though). IMO, stating what happens to bogus values at the beginning of the switch block is just as clear as doing the same thing with if and continue statements at the beginning of a foreach loop. Benj On October 8, 2004 12:10 am, Ron Korving wrote:

Christian Schneider

21 years ago
Benj Carson wrote:
> Coming from C (or Java), I find the new behaviour a little strange. If you
I fully agree. Although I wouldn't have used the word 'little' here :-)
> use default to match invalid conditions, putting it at the beginning of a > switch doesn't seem to be poor practice to me (putting it in the middle
Even putting in the middle makes sense IMHO: Looking at some of my code I found constructs like switch ($sort) { case 'firstname': ... default: case 'lastname': ... case 'email': ... } which seems completely legal and understandable to me: I can sort by different fields (which have a natural order in my data structure so that's how I list them) and one of them happens to be the default if $sort is not set. I don't think it's up to the programming language to judge if such a construct makes sense or not.
> On October 8, 2004 12:10 am, Ron Korving wrote: >>assume you're experiencing now. You could've seen this coming. When you >>write a switch, think of it as the input being matched case by case, with >>"default" being the case that matches anything. This means you don't >>wanna place the default case anywhere but at the bottom.
But the important thing is that PHP4 DOES NOT IMPLEMENT IT THIS WAY! php -r '$a = 1; switch ($a) { default: print "0\n"; break; case 1: print "1\n"; }' prints 1 for PHP 4.3.9 (but prints 0 for 5.1.0-dev) So a) the documentation does not match the PHP behaviour people got used to, b) it is different to every other language having a switch statement I know, c) it would be a nasty BC break to change it now. I strongly suggest that the behaviour is defined a la C (the position of default: does not matter) and the documentation is changed accordingly! There is 1000 times more PHP 4 code around (which may rely on the C-like behaviour) than PHP 5 code so we still have time. But not much. We have to resort this as quickly as possible to avoid a big mess... - Chris

Ron Korving

21 years ago
Well, you convinced me (no need to get all physical with me tho ;)). If this is how C acts (which I did not know), then I prefer it to work like this too. I always assumed (which is bad, I know) the default case worked like a "catch all", which catches anything that crosses its path, and therefor needed to be defined as the last case in the switch. Apparently, this is not the case throughout the history of the switch statement (which I didn't know), so I agree with you, especially since this has worked in PHP4. Ron "Christian Schneider" <cschneid@cschneid.com> schreef in bericht news:416667C3.5090506@cschneid.com...
> Benj Carson wrote: > > Coming from C (or Java), I find the new behaviour a little strange. If
you
> > I fully agree. Although I wouldn't have used the word 'little' here :-) > > > use default to match invalid conditions, putting it at the beginning of
a
> > switch doesn't seem to be poor practice to me (putting it in the middle > > Even putting in the middle makes sense IMHO: > Looking at some of my code I found constructs like > switch ($sort) > { > case 'firstname': ... > default: case 'lastname': ... > case 'email': ... > } > which seems completely legal and understandable to me: I can sort by > different fields (which have a natural order in my data structure so > that's how I list them) and one of them happens to be the default if > $sort is not set. I don't think it's up to the programming language to > judge if such a construct makes sense or not. > > > On October 8, 2004 12:10 am, Ron Korving wrote: > >>assume you're experiencing now. You could've seen this coming. When you > >>write a switch, think of it as the input being matched case by case,
with

Sascha Schumann

21 years ago
Andi, from the feedback it is obvious that the engine supported defaults at places other than the bottom. In all switch-supporting languages I know, it is possible to do this: switch ($expr) { default: /* handle everything EXCEPT "foo" and "bar" */ /* fall-through */ case 'foo': case 'bar': /* handle everything */ break; } Why should the support of this be discontinued? - Sascha On Thu, 7 Oct 2004, Andi Gutmans wrote:

Andi Gutmans

21 years ago
I will look into the reason this seems to have changed. However, I can assure you that from day 1 this was not supposed to work and was documented as such for years already (since the days of PHP 3). If it worked at some point then it was by chance! Andi At 05:31 PM 10/8/2004 +0200, Sascha Schumann wrote:

Jason Garber

21 years ago
Hello, Ergh. I also hope that it can easily be restored to work the way it did, even if that was undocumented. The thought of looking through ~ 5,000 php scripts before our upgrade is a bit overwhelming :)
-- Best regards, Jason mailto:jason@ionzoft.com Friday, October 8, 2004, 11:52:54 AM, you wrote: AG> I will look into the reason this seems to have changed. AG> However, I can assure you that from day 1 this was not supposed to work AG> and was documented as such for years already (since the days of PHP 3). If AG> it worked at some point then it was by chance! AG> Andi

Christian Schneider

21 years ago
Andi Gutmans wrote:
> However, I can assure you that from day 1 this was not supposed to work > and was documented as such for years already (since the days of PHP 3). > If it worked at some point then it was by chance!
This would be a good time to accept the defacto standard, redefine switch() in the documentation to what it actually does (up to and including 5.0.2, even if this is by chance), add test cases and make sure we have a consistent behaviour from now on. Or is anyone in favour of the documented-but-never-working behavour? Over and out, - Chris

Wez Furlong

21 years ago
Slightly OT, but while we are on the subject of switch not being C-ish, how about making it so that continue inside a switch block behaves the way it does in C? This C code snippet: while (1) { printf("top\n"); switch (1) { case 1: continue; } printf("bork\n"); } will print out "top\n" repeatedly. The same code in PHP will print out "top\nbork\n" repeatedly. The get the same behaviour as the C code you need to use continue 2 instead. IMO, this is awful, and at first I thought it was a BC break, but it seems that the stock RHEL 4.3.2 version of PHP behaves the same way. What, if anything, should we do about this? --Wez.

Hartmut Holzgraefe

21 years ago
Wez Furlong wrote:
> What, if anything, should we do about this?
two letters: 'BC' :(
-- Hartmut Holzgraefe <hartmut@php.net>

Andi Gutmans

21 years ago
I don't think we should do anything about it. From day 1 we treated switch() like a loop as far as break/continue is concerned, mainly because we wanted break/continue to be consistent. You might find this odd but you actually have more power in PHP than in C as you can break out or continue from multiple loops. In my opinion this is definitely not something which should be changed at this point. BTW, I think we have a fix for the switch() thingy. I still have to look at it more closely before commiting though. Andi At 05:37 PM 10/8/2004 +0100, Wez Furlong wrote:

Andi Gutmans

21 years ago
Fixed. At 12:00 PM 10/8/2004 -0400, Jason Garber wrote: