digitalmars.D - switch()
- Manu (109/109) Feb 16 2014 So D offers great improvements to switch(), but there are a few small
- Chris Cain (13/13) Feb 16 2014 I think the main reason why switches work this way (and
- Chris Cain (8/11) Feb 16 2014 I feel the need to clarify: I really don't mean all of the
- Manu (3/5) Feb 16 2014 final switch requires you to implement every possible case, so it makes ...
- Manu (8/18) Feb 16 2014 Okay, but that doesn't address the range cases...
- Mike Parker (25/29) Feb 16 2014 I only get the error when falling through to default, in which case it s...
- Steven Schveighoffer (5/20) Feb 16 2014 This is allowed, because there is no code between the case statements.
- "Casper =?UTF-8?B?RsOmcmdlbWFuZCI=?= <shorttail hotmail.com> (12/12) Feb 16 2014 What about new evolved switch statement, called something as to
- Namespace (9/22) Feb 16 2014 I like 'match' as Rust has:
- Asman01 (7/32) Feb 17 2014 +1, I linked this "match". How a name does the difference. I
- Mike Parker (3/6) Feb 16 2014 That hit me this morning when I woke up. It's the reason I got the error...
- Timon Gehr (40/129) Feb 16 2014 Sure.
- Manu (34/95) Feb 16 2014 That's still entirely explicit. It's not fallthrough.
- Chris Cain (15/26) Feb 17 2014 I know I'm weird here, but I disagree. I had no idea what you
- Manu (16/41) Feb 17 2014 I'm dealing with arbitrary values as appearing in midi files.
- Timon Gehr (14/35) Feb 17 2014 Obviously. Hence, no need to point this out.
- Nick Sabalausky (5/19) Feb 17 2014 I find it extremely easy to read, and much nicer than the other options....
- Walter Bright (9/23) Feb 16 2014 It's that way to prevent confusion from people used to C/C++, and/or
- Jacob Carlborg (5/9) Feb 16 2014 Isn't that what final switches are for? Or are default statements not
- Walter Bright (3/10) Feb 16 2014 Right, they aren't.
- Manu (46/79) Feb 16 2014 I figured that, but deliberately gimping a construct that could be far m...
- Walter Bright (8/12) Feb 17 2014 I tend to agree with Andrei on this - the proposals aren't fundamental o...
- Manu (45/60) Feb 17 2014 Refer to my other reply wrt the 'rubble' concept.
- Walter Bright (8/14) Feb 17 2014 I have a real hard time seeing the proposed changes as radical or game c...
- Manu (38/58) Feb 17 2014 I think abstracting away volumes of comparative matching logic is simila...
- Nick Sabalausky (13/20) Feb 17 2014 There was a HUGE debate on all this back when the feature was first
- Ary Borenszweig (2/12) Feb 17 2014 Could you show an example of such scenario? I don't get it.
- Walter Bright (3/9) Feb 17 2014 Having a set of bit flags, and adding another bit flag later, and failin...
- Ary Borenszweig (17/27) Feb 17 2014 auto bit_flag = ...;
- Walter Bright (4/6) Feb 17 2014 Because if you account for all the cases, you write:
- Steven Schveighoffer (20/29) Feb 17 2014 Would it not be better to infer this, and you could override it by doing...
- Walter Bright (5/6) Feb 17 2014 Because it makes the programmer's intent clear - are all the cases accou...
- Steven Schveighoffer (7/13) Feb 18 2014 I think your anecdotal experience with exception specification in Java i...
- Ary Borenszweig (5/21) Feb 18 2014 Exactly. Programmers will just put "default: break" because of this
- Walter Bright (3/6) Feb 18 2014 final is meaningless with a default.
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (5/11) Feb 19 2014 A better warning/error message may help here. Please have a look
- Daniel Murphy (6/12) Feb 18 2014 It's not really the same, because silencing checked exceptions results i...
- Steven Schveighoffer (11/25) Feb 18 2014 My point though, is that the change to require default gains you nothing...
- Steven Schveighoffer (4/6) Feb 18 2014 *implementing*, not implementation :)
- Daniel Murphy (16/18) Feb 18 2014 It only gains you nothing if you respond to the error by mindlessly putt...
- Steven Schveighoffer (9/19) Feb 18 2014 It may not be mindless. Most people who want to handle the default case ...
- Ary Borenszweig (2/4) Feb 18 2014 Lol, I swear I didn't read your answer before posting mine.
- Daniel Murphy (8/14) Feb 19 2014 So why not put an assert(0) in instead of a break? Tell the compiler th...
- Ary Borenszweig (9/19) Feb 19 2014 Sometimes you don't care about other values, which is different than not...
- QAston (4/32) Feb 19 2014 Just put default: break instead of that comment, it's shorter
- Steven Schveighoffer (4/12) Feb 20 2014 I think the comment was meant as an explanation to you, not something th...
- Steven Schveighoffer (22/36) Feb 20 2014 Putting default: assert(0); changes the meaning of the code. In other
- Daniel Murphy (7/26) Feb 20 2014 Are we talking about writing new code or porting C/C++ code? If the lat...
- Ary Borenszweig (20/39) Feb 18 2014 The compiler should force you to write an "else" for every if then:
- Walter Bright (5/9) Feb 18 2014 This was fiercely debated at length and settled here years ago. It isn't...
- Steven Schveighoffer (15/26) Feb 20 2014 I thought it was a more recent change than years ago. When was the chang...
- bearophile (6/8) Feb 20 2014 I have written tons of D2 code in the last years, and such
- Steven Schveighoffer (4/10) Feb 20 2014 But what about default: break;?
- Daniel Murphy (9/11) Feb 20 2014 I just did a quick git-grep on the compiler source (not D, but all switc...
- Steven Schveighoffer (12/23) Feb 20 2014 Good data, but I was more thinking of people who use D, not the core
- Manu (8/37) Feb 20 2014 In my little app:
- Ary Borenszweig (7/30) Feb 20 2014 Did you put those "default: break;" because:
- Manu (7/50) Feb 20 2014 Because the compiler told me. It's not a habit of mine to type it.
- Manu (3/12) Feb 17 2014 I think 'final switch' should do that for you, and by typing final, you'...
- Walter Bright (2/4) Feb 17 2014 That's why a default case is not allowed for a 'final' switch.
- Manu (13/26) Feb 17 2014 It sounds like that's basically the same as final switch, just without t...
- Walter Bright (2/11) Feb 17 2014 The 'final' works as you propose. Why not give it a whirl?
- Andrei Alexandrescu (28/138) Feb 16 2014 TL;DR of my answer to this: at some point we must get used to the notion...
- Manu (120/273) Feb 17 2014 OT: Do you realise how harsh your posts often appear to people? I often
- Andrei Alexandrescu (35/88) Feb 17 2014 You're right. I shouldn't have answered because now the thread is
- Dejan Lekic (16/69) Feb 17 2014 And do you realise that every sentence in your post is matter
- Manu (19/35) Feb 17 2014 Yes, they're obviously opinions. I wouldn't use phrasing like that if I
- Walter Bright (3/10) Feb 17 2014 Having strong convictions is good, but strong reactions to them come wit...
- Walter Bright (15/33) Feb 17 2014 I tend to format such like this:
- Manu (28/44) Feb 17 2014 Me too, but you don't feel this is basically a hack?
- Walter Bright (5/27) Feb 17 2014 I see nothing hackish about it. After all, there's a reason D does not e...
- Brian Schott (2/4) Feb 17 2014 http://www.youtube.com/watch?feature=player_detailpage&v=KM2K7sV-K74#t=5
- Manu (9/11) Feb 17 2014 I didn't say that. But I do think it's more significant than it appears.
- Nick Sabalausky (14/56) Feb 17 2014 Sounds like you need elastic tabstops:
- "Casper =?UTF-8?B?RsOmcmdlbWFuZCI=?= <shorttail hotmail.com> (10/15) Feb 18 2014 I have code formatting OCD. Switch case is an abomination. It
- QAston (28/33) Feb 19 2014 There are other ways in D to deal with repetition. For people
- Kenji Hara (5/24) Feb 17 2014 I completely agree with Andrei. We should continue to keep that D is the
- Manu (5/32) Feb 17 2014 I agree, to an extent. That's why I say if it is to be improved, I guess...
- Daniel Murphy (4/10) Feb 17 2014 Exactly, foreach is a new, better language construct, but we didn't butc...
- Andrei Alexandrescu (5/15) Feb 17 2014 A "match" statement that figures type patterns and introduce names and
- Andrej Mitrovic (8/11) Feb 17 2014 There are some interesting related Phobos pulls:
- Daniel Murphy (7/11) Feb 17 2014 I doubt one can really know if it's a game changer until it has been
- Nick Sabalausky (5/12) Feb 17 2014 Although I've said it before, I'd love to see Nemerle's match in D:
- Kapps (21/40) Feb 17 2014 I do agree that the breaks can get rather messy and I don't think
- Damian Day (8/145) Feb 17 2014 Having also wrote a lot of switch statements in D I do mostly
- deadalnix (5/20) Feb 18 2014 When implementing this on SDC. The .. syntax seems appropriate to
So D offers great improvements to switch(), but there are a few small things I wonder about. 1. case fall-through is not supported; explicit 'goto case n;' is required. With this in mind, 'break' is unnecessary. Why is it required? It could be implicit upon reaching the next case label, or a scope could be used (with support for omitting the scope for single statements as with if). It's really noisy, and annoying to write everywhere. 2. 'case 1, 3, 7, 8:' is awesome! ...but ranged cases have a totally different syntax: 'case 1: .. case 3:' Why settle on that syntax? The inconsistency looks kinda silly when they appear together in code. Surely it's possible to find a syntax that works without repeating case and ':'? It's also weird, because it seems that 'case n: .. case m:' is inclusive of m. This may be unexpected. I'm not sure it's reasonable to use the '..' syntax in this case for that reason. '..' is an [) range, case ranges must be [] so that it makes sense when dealing with enum key ranges. 3. Why is 'default' necessary? If I'm not switching on an enumerated type, then many values are meaningless. requiring an empty 'default: break;' line at the end is annoying and noisy. I often find myself tempted to rewrite blocks of successive if() logic comparing integers against values/ranges, but it looks silly since the scope rules are not explicit, and 'default: break;' always wastes an extra line. I like to reduce noise in my code, and these switch semantics threaten to simplify a lot of code, if not for these strange decisions (purely for legacy compliance?). Let's consider an example: Code like this: int difficulty = -1; if(e.note.note >= 60 && e.note.note < 72) difficulty = 0; else if(e.note.note >= 72 && e.note.note < 84) difficulty = 1; else if(e.note.note >= 84 && e.note.note < 96) difficulty = 2; else if(e.note.note >= 96 && e.note.note < 108) difficulty = 3; The repetition of e.note.note is annoying, and particular choice of comparisons are liable to result in out-by-ones. It's not nice code to read. Rewrites like this: int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; } That's horrid, it's much longer! And there are pointless wasted lines everywhere. The default case is a total waste, since -1 should just be assigned when initialising the variable above. We can compact it a bit like this: int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; } But that's horrible too. It's not clear what vertical offset the 'break' statements shoudl appear at (I hate stacking up multiple statements across the same line!). The the default case is still a waste. Ideally: int difficulty = -1; switch(e.note.note) { case 60 .. 72: difficulty = 0; case 72 .. 84: difficulty = 1; case 84 .. 96: difficulty = 2; case 96 .. 108: difficulty = 3; } 'break's are unnecessary since fallthrough isn't allowed. Proper numeric range could be supported (assuming [) intervals). 'default' case is unnecessary, and removed. The switch and braces results in 3 extra lines, but I still feel this level of simplification results in code that is MUCH more readable than the sequence of if's I started with. It's super obvious what's going on. I have quite many blocks like this. A great man once (actually, frequently) said "If it doesn't look right, it probably isn't".
Feb 16 2014
I think the main reason why switches work this way (and cannot/should not be changed) is because of one of the main design goals of D: http://dlang.org/overview.html the same or issue an error. The proposed changes would violate this, making existing C code change meaning silently (wrt implicit "break;" in particular). TBH, though, I agree that this is somewhat of a speed bump in D. I really rarely find myself using switches because of the same issues you mention. Unfortunately, without adding new syntax (which is also problematic for many reasons), such a thing cannot be fixed unless this goal is ignored.
Feb 16 2014
On Sunday, 16 February 2014 at 16:04:53 UTC, Chris Cain wrote:http://dlang.org/overview.html behave the same or issue an error.I feel the need to clarify: I really don't mean all of the proposed changes are bad for this reason, but one of the ones I would find most value in (implicit "break;"s) is inappropriate. Sorry for the double post. I do like the suggestions in spirit. ** I'm also surprised "default" is necessary. I thought it was only necessary in final switches.
Feb 16 2014
On 17 February 2014 02:08, Chris Cain <clcain uncg.edu> wrote:** I'm also surprised "default" is necessary. I thought it was only necessary in final switches.final switch requires you to implement every possible case, so it makes no sense in that case.
Feb 16 2014
On 17 February 2014 02:04, Chris Cain <clcain uncg.edu> wrote:I think the main reason why switches work this way (and cannot/should not be changed) is because of one of the main design goals of D: http://dlang.org/overview.html or issue an error. The proposed changes would violate this, making existing C code change meaning silently (wrt implicit "break;" in particular).Okay, but that doesn't address the range cases... TBH, though, I agree that this is somewhat of a speed bump in D. I reallyrarely find myself using switches because of the same issues you mention. Unfortunately, without adding new syntax (which is also problematic for many reasons), such a thing cannot be fixed unless this goal is ignored.I agree, I rarely use switch statements for the same reason. Deliberately gimping a very useful control statement because it's shit in another language (it really is!), seems like an extremely lame design goal to me. switch could be so much more useful with these changes. I suspect most people would avoid it much of the time for these reasons.
Feb 16 2014
On 2/17/2014 12:42 AM, Manu wrote:So D offers great improvements to switch(), but there are a few small things I wonder about. 1. case fall-through is not supported; explicit 'goto case n;' is required.I only get the error when falling through to default, in which case it says: Error: switch case fallthrough - use 'goto default;' if intended Fall-through compiles and runs otherwise. This is something I'm doing right now: switch( event.type ) { // No error on falling through here <<<---------------------. case SDL_KEYDOWN: case SDL_KEYUP: if( _keyHandler ) { _keyHandler( cast( Key )event.key.keysym.scancode, cast( KeyState )event.key.state, cast( KeyModifier )event.key.keysym.mod ); } break; case SDL_WINDOWEVENT: handleWindowEvent( &event.window ); break; case SDL_QUIT: if( _quitHandler ) { _quitHandler(); } break; default: break; }
Feb 16 2014
On Sun, 16 Feb 2014 11:37:48 -0500, Mike Parker <aldacron gmail.com> wrote:On 2/17/2014 12:42 AM, Manu wrote:This is allowed, because there is no code between the case statements. It's the one case where fallthrough is allowed. If you put a statement in between the two, it would complain. -SteveSo D offers great improvements to switch(), but there are a few small things I wonder about. 1. case fall-through is not supported; explicit 'goto case n;' is required.I only get the error when falling through to default, in which case it says: Error: switch case fallthrough - use 'goto default;' if intended Fall-through compiles and runs otherwise. This is something I'm doing right now: switch( event.type ) { // No error on falling through here <<<---------------------. case SDL_KEYDOWN: case SDL_KEYUP:
Feb 16 2014
What about new evolved switch statement, called something as to not confuse it with C syntax? It could be a simple rewrite thing. mysteryswitch (some expression) { case 1: some statement; case 2 .. 4: some other statement; } could rewrite to switch (some expression) { case 1: some statement; break; case 2: .. case 4: some other statement; break; default: break; }
Feb 16 2014
On Monday, 17 February 2014 at 00:22:52 UTC, Casper Færgemand wrote:What about new evolved switch statement, called something as to not confuse it with C syntax? It could be a simple rewrite thing. mysteryswitch (some expression) { case 1: some statement; case 2 .. 4: some other statement; } could rewrite to switch (some expression) { case 1: some statement; break; case 2: .. case 4: some other statement; break; default: break; }I like 'match' as Rust has: ---- match (some expression) { case 1: some statement; case 2 .. 4: some other statement; } ----
Feb 16 2014
On Monday, 17 February 2014 at 00:27:44 UTC, Namespace wrote:On Monday, 17 February 2014 at 00:22:52 UTC, Casper Færgemand wrote:+1, I linked this "match". How a name does the difference. I suggest to implement this one instead of. I think that it's very nice because don't make nobody confusing anymore or break D philosofy. some-statement should have an implicit 'break' generated by the compiler just like Pascal cases have (and rust I guess)What about new evolved switch statement, called something as to not confuse it with C syntax? It could be a simple rewrite thing. mysteryswitch (some expression) { case 1: some statement; case 2 .. 4: some other statement; } could rewrite to switch (some expression) { case 1: some statement; break; case 2: .. case 4: some other statement; break; default: break; }I like 'match' as Rust has: ---- match (some expression) { case 1: some statement; case 2 .. 4: some other statement; } ----
Feb 17 2014
On 2/17/2014 5:57 AM, Steven Schveighoffer wrote:This is allowed, because there is no code between the case statements. It's the one case where fallthrough is allowed. If you put a statement in between the two, it would complain.That hit me this morning when I woke up. It's the reason I got the error when I fell through to default.
Feb 16 2014
On 02/16/2014 04:42 PM, Manu wrote:So D offers great improvements to switch(), but there are a few small things I wonder about. 1. case fall-through is not supported; explicit 'goto case n;' is required.Yes it is supported. Use 'goto case;'.With this in mind, 'break' is unnecessary.Sure.Why is it required?Backwards compatibility.It could be implicit upon reaching the next case label, or a scope could be used (with support for omitting the scope for single statements as with if). It's really noisy, and annoying to write everywhere. ...Like this: http://ceylon-lang.org/documentation/reference/statement/switch/ ?2. 'case 1, 3, 7, 8:' is awesome! ...but ranged cases have a totally different syntax: 'case 1: .. case 3:' Why settle on that syntax? The inconsistency looks kinda silly when they appear together in code. Surely it's possible to find a syntax that works without repeating case and ':'? ...AFAIK it is to emphasize that the range is inclusive, as opposed to: case 1..3: IIRC Walter's intention was to format it as follows: switch(x){ case 1: .. case 3: }It's also weird, because it seems that 'case n: .. case m:' is inclusive of m. This may be unexpected. I'm not sure it's reasonable to use the '..' syntax in this case for that reason. '..' is an [) range, case ranges must be [] so that it makes sense when dealing with enum key ranges. ...Sure, mixing case lists and ranges in a single statement would be neat, but what would be your preferred syntax?3. Why is 'default' necessary? If I'm not switching on an enumerated type, then many values are meaningless. requiring an empty 'default: break;' line at the end is annoying and noisy. ...There is more than one sensible default, so being explicit about the default makes sense.I often find myself tempted to rewrite blocks of successive if() logic comparing integers against values/ranges, but it looks silly since the scope rules are not explicit, and 'default: break;' always wastes an extra line. I like to reduce noise in my code, and these switch semantics threaten to simplify a lot of code, if not for these strange decisions (purely for legacy compliance?). Let's consider an example: Code like this: int difficulty = -1; if(e.note.note >= 60 && e.note.note < 72) difficulty = 0; else if(e.note.note >= 72 && e.note.note < 84) difficulty = 1; else if(e.note.note >= 84 && e.note.note < 96) difficulty = 2; else if(e.note.note >= 96 && e.note.note < 108) difficulty = 3; The repetition of e.note.note is annoying, and particular choice of comparisons are liable to result in out-by-ones. It's not nice code to read. Rewrites like this: int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; } That's horrid, it's much longer! And there are pointless wasted lines everywhere.The wasted lines are due to your formatting. int difficulty=-1; switch(e.note.note){ case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: break; } Of course, I'd just write the above as: int difficulty = e.note.note.between(60,108) ? (e.note.note-60)/12 : -1;The default case is a total waste, since -1 should just be assigned when initialising the variable above. ...How is the compiler supposed to know? It might be a logic error for e.note.note to be out of range.... Ideally: int difficulty = -1; switch(e.note.note) { case 60 .. 72: difficulty = 0; case 72 .. 84: difficulty = 1; case 84 .. 96: difficulty = 2; case 96 .. 108: difficulty = 3; } ...Ideally closer to: int difficulty = switch(e.note.note){ 60 .. 72 => 0; 73 .. 84 => 1; 84 .. 96 => 2; 96 .. 108 => 3; _ => -1; };
Feb 16 2014
On 17 February 2014 03:14, Timon Gehr <timon.gehr gmx.ch> wrote:On 02/16/2014 04:42 PM, Manu wrote:That's still entirely explicit. It's not fallthrough. It could be implicit upon reaching the next case label, or a scope couldSo D offers great improvements to switch(), but there are a few small things I wonder about. 1. case fall-through is not supported; explicit 'goto case n;' is required.Yes it is supported. Use 'goto case;'.Yes. That's just common sense, right? 2.be used (with support for omitting the scope for single statements as with if). It's really noisy, and annoying to write everywhere. ...Like this: http://ceylon-lang.org/documentation/reference/ statement/switch/ ?Right. Inclusive ranges are intended for enum ranges though. Integer ranges are just fine in the usual way. I'd support both... It's also weird, because it seems that 'case n: .. case m:' is inclusive'case 1, 3, 7, 8:' is awesome! ...but ranged cases have a totally different syntax: 'case 1: .. case 3:' Why settle on that syntax? The inconsistency looks kinda silly when they appear together in code. Surely it's possible to find a syntax that works without repeating case and ':'? ...AFAIK it is to emphasize that the range is inclusive, as opposed to: case 1..3: IIRC Walter's intention was to format it as follows: switch(x){ case 1: .. case 3: }case 1, 2, 5..10, 20: But that's not what I actually meant. I was actually talking about the case when 'case 1,2,5:' appears in the same switch() block as 'case 10: .. case 19:', when they appear next to eachother, it just looks awkward; like they don't belong together. 3.of m. This may be unexpected. I'm not sure it's reasonable to use the '..' syntax in this case for that reason. '..' is an [) range, case ranges must be [] so that it makes sense when dealing with enum key ranges. ...Sure, mixing case lists and ranges in a single statement would be neat, but what would be your preferred syntax?Don't agree. Most of my cases are such that no default action is required. It's just noise in my code. If I fail to handle default when I probably should have, then that's clearly my mistake. The wasted lines are due to your formatting.Why is 'default' necessary? If I'm not switching on an enumerated type, then many values are meaningless. requiring an empty 'default: break;' line at the end is annoying and noisy. ...There is more than one sensible default, so being explicit about the default makes sense.int difficulty=-1; switch(e.note.note){ case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: break; }I hate this. It violates the formatting conventions used EVERYWHERE else. In terms of formatting, it doesn't even look like the same language. Of course, I'd just write the above as:int difficulty = e.note.note.between(60,108) ? (e.note.note-60)/12 : -1;Yes yes, very clever. Obviously it's an example and could come in any shape or form. Personally, I also wouldn't do that anyway; basic readability has definitely been lost. The default case is a total waste, since -1 should just be assigned whenThen I should have used an invariant or something actually designed for catching values out of range. It's not the compilers fault I made a logic error. I could make a logic error literally anywhere in my code. Why force an annoying rule to maybe sometimes catch exactly one case (while making other competing cases where a logic error isn't present more annoying).initialising the variable above. ...How is the compiler supposed to know? It might be a logic error for e.note.note to be out of range.
Feb 16 2014
On Monday, 17 February 2014 at 04:00:08 UTC, Manu wrote:Of course, I'd just write the above as:I know I'm weird here, but I disagree. I had no idea what you were doing at the beginning of the topic, but that one line revealed to me that this is likely related to the music game thing you proposed awhile ago. I can't really explain why "note" was insufficient before to reveal that, but once I saw "12" explicitly on its own I immediately thought ~"12 ... semitones ... octaves ... note ... it's music ... he was working on a music game ... he came up with this while working on the music game". So, it's classifying difficulty based on which octave a note is for your music game? Of course, I might be wrong here. It just seems to me that the reducing of information made it clearer what the purpose is disregarding the other contextual information that probably exists outside of what you're trying to show us.int difficulty = e.note.note.between(60,108) ? (e.note.note-60)/12 : -1;Yes yes, very clever. Obviously it's an example and could come in any shape or form. Personally, I also wouldn't do that anyway; basic readability has definitely been lost.
Feb 17 2014
On 17 February 2014 22:38, Chris Cain <clcain uncg.edu> wrote:On Monday, 17 February 2014 at 04:00:08 UTC, Manu wrote:I'm dealing with arbitrary values as appearing in midi files. There is a relationship that you made, kind of... but it's incidental. It's actually an abuse of the structure of a midi file to relate concepts to octaves; designers use the separation of octaves in midi composition software to separate some arbitrary data, because octaves often provide good visual separation in editors, making it easier to visualise the data they're authoring. It's also just the one that was on my screen when I cut and pasted. There are lots of others that lead me to consider this as a frequently recurring pattern and become annoyed that my code was was uniformly ugly. Of course, I might be wrong here. It just seems to me that the reducing ofOf course, I'd just write the above as:I know I'm weird here, but I disagree. I had no idea what you were doing at the beginning of the topic, but that one line revealed to me that this is likely related to the music game thing you proposed awhile ago. I can't really explain why "note" was insufficient before to reveal that, but once I saw "12" explicitly on its own I immediately thought ~"12 ... semitones ... octaves ... note ... it's music ... he was working on a music game ... he came up with this while working on the music game". So, it's classifying difficulty based on which octave a note is for your music game?int difficulty = e.note.note.between(60,108) ? (e.note.note-60)/12 : -1;Yes yes, very clever. Obviously it's an example and could come in any shape or form. Personally, I also wouldn't do that anyway; basic readability has definitely been lost.information made it clearer what the purpose is disregarding the other contextual information that probably exists outside of what you're trying to show us.The purpose is kinda unrelated conceptually. In reality, what has happened is that you have become confused. You were searching for reason where there is none, and the algorithmic expression lead you to a false conclusion :)
Feb 17 2014
On 02/17/2014 04:59 AM, Manu wrote:On 17 February 2014 03:14, Timon Gehr <timon.gehr gmx.ch ... Of course, I'd just write the above as: int difficulty = e.note.note.between(60,108) ? (e.note.note-60)/12 : -1; Yes yes, very clever.I can't agree.Obviously it's an example and could come in any shape or form.Obviously. Hence, no need to point this out.Personally, I also wouldn't do that anyway; basic readability has definitely been lost. ...IMO quite the opposite is true. And everything around it will tend to become simpler to follow at a glance as well.The default case is a total waste, since -1 should just be assigned when initialising the variable above. ... How is the compiler supposed to know? It might be a logic error for e.note.note to be out of range. Then I should have used an invariant or something actually designed for catching values out of range. It's not the compilers fault I made a logic error. I could make a logic error literally anywhere in my code. Why force an annoying ruleIt's not inherent to the rule.to maybe sometimes catch exactly one caseWell, it is also not the kind of error I make, but it still documents intention. It would be easy to sloppily omit default: assert(0) without this rule without actually affecting correct code, but I wouldn't warmly recommend this practice.(while making other competing cases where a logic error isn't present more annoying).That's roughly the dynamic typing argument. Obviously 'switch' is quite lame (being lame seems to be an inherent quality of statement-based syntax), but the requirement to explicitly handle the default case instead of implicitly skipping it is not why.
Feb 17 2014
On 2/16/2014 10:59 PM, Manu wrote:On 17 February 2014 03:14, Timon Gehr <timon.gehr gmx.ch> wrote:I find it extremely easy to read, and much nicer than the other options. Being able to omit break and use switch as an expression would be a little nicer still, but I still fail to see why the above, no matter how it's formatted, is so terribly intolerable.int difficulty=-1; switch(e.note.note){ case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: break; }I hate this. It violates the formatting conventions used EVERYWHERE else. In terms of formatting, it doesn't even look like the same language.
Feb 17 2014
On 2/16/2014 7:42 AM, Manu wrote:1. case fall-through is not supported; explicit 'goto case n;' is required. With this in mind, 'break' is unnecessary. Why is it required?It's that way to prevent confusion from people used to C/C++, and/or transliterating code from such to D.2. 'case 1, 3, 7, 8:' is awesome! ...but ranged cases have a totally different syntax: 'case 1: .. case 3:' Why settle on that syntax? The inconsistency looks kinda silly when they appear together in code. Surely it's possible to find a syntax that works without repeating case and ':'?Many syntaxes were proposed for that, and this was the best one.I'm not sure it's reasonable to use the '..' syntax in this case for that reason. '..' is an [) range, case ranges must be [] so that it makes sense when dealing with enum key ranges.That was the known problem with using a..b3. Why is 'default' necessary? If I'm not switching on an enumerated type, then many values are meaningless. requiring an empty 'default: break;' line at the end is annoying and noisy.It originally was not required, but there was a campaign by a lot of D users to make it required to deal with the common bug of adding a value in one switch statement but forgetting to add it to another corresponding one.if not for these strange decisions (purely for legacy compliance?).I hope you'll find them less strange now.
Feb 16 2014
On 2014-02-16 21:03, Walter Bright wrote:It originally was not required, but there was a campaign by a lot of D users to make it required to deal with the common bug of adding a value in one switch statement but forgetting to add it to another corresponding one.Isn't that what final switches are for? Or are default statements not allowed in final switches at all? -- /Jacob Carlborg
Feb 16 2014
On 2/16/2014 12:06 PM, Jacob Carlborg wrote:On 2014-02-16 21:03, Walter Bright wrote:Final switches only help for enums.It originally was not required, but there was a campaign by a lot of D users to make it required to deal with the common bug of adding a value in one switch statement but forgetting to add it to another corresponding one.Isn't that what final switches are for?Or are default statements not allowed in final switches at all?Right, they aren't.
Feb 16 2014
On 17 February 2014 06:03, Walter Bright <newshound2 digitalmars.com> wrote:On 2/16/2014 7:42 AM, Manu wrote:I figured that, but deliberately gimping a construct that could be far more useful than it is, just because it was crap in some other language seems like a poor choice to me. 2. 'case 1, 3, 7, 8:' is awesome! ...but ranged cases have a totally1. case fall-through is not supported; explicit 'goto case n;' is required. With this in mind, 'break' is unnecessary. Why is it required?It's that way to prevent confusion from people used to C/C++, and/or transliterating code from such to D.Yeah, but when I suggest a..b, I suggest applying existing [) range rules, as would be expected. It doesn't make sense for enum keys, and I think the existing syntax is acceptable for [] usage with enum keys, but you're not always switching on enums. Perhaps supporting both would be useful, where a..b is [) as expected, and 'case A: .. case B:' is [] for use with enums? 3. Why is 'default' necessary? If I'm not switching on an enumerated type,different syntax: 'case 1: .. case 3:' Why settle on that syntax? The inconsistency looks kinda silly when they appear together in code. Surely it's possible to find a syntax that works without repeating case and ':'?Many syntaxes were proposed for that, and this was the best one. I'm not sure it's reasonable to use the '..' syntax in this case for thatreason. '..' is an [) range, case ranges must be [] so that it makes sense when dealing with enum key ranges.That was the known problem with using a..bIsn't that the entire point of final switch? Why introduce final switch to address that, then do this aswell? if not for these strange decisions (purely for legacy compliance?).then many values are meaningless. requiring an empty 'default: break;' line at the end is annoying and noisy.It originally was not required, but there was a campaign by a lot of D users to make it required to deal with the common bug of adding a value in one switch statement but forgetting to add it to another corresponding one.Well, I get them, but it seems like an awful lot of missed opportunities. D threatens to improve substantially on C switch, but it only goes half way, resulting in something that's only slightly nicer if used precisely in the 'C way'. It doesn't offer any new use cases, which is only really inhibited by some quite trivial decisions. Maybe a new and improved syntax for D that can be lowered? 'select()'? 'match()'? I would set it up with proper scoping syntax: match([x =] expression) { case(1, 3, 4, 6) // use parentheses like all other control statements? { proper scope block... goto named_case; } case(10..20) // [) interval singleStatement(); case(2, 5, 7..10) // this would be handy too singleStatement(); case named_case // it's a useful concept; explicit named case for shared work, which others can jump to. not sure how best to express it... sharedOperation(); default { // surely this should be optional? } } I think a really useful construct could be made out of switch, but it seems that it won't happen because it must support C code unchanged.I hope you'll find them less strange now.
Feb 16 2014
On 2/16/2014 7:39 PM, Manu wrote:I think a really useful construct could be made out of switch, but it seems that it won't happen because it must support C code unchanged.I tend to agree with Andrei on this - the proposals aren't fundamental or game changing, and are kinda just bouncing the rubble around (po-tay-to vs po-tah-to).Isn't that the entire point of final switch? Why introduce final switch to address that, then do this aswell?Implicit in your questions is switches will only be used on enums, i.e. all the values a type can be are known to the compiler. This is only true for a smallish subset of types that are switched on. final switch : for enums default : for everything else
Feb 17 2014
On 17 February 2014 18:43, Walter Bright <newshound2 digitalmars.com> wrote:On 2/16/2014 7:39 PM, Manu wrote:Refer to my other reply wrt the 'rubble' concept. I think a quality implementation would be fairly game changing. A properly scoped and fully featured switch/select/match statement would result in some radical simplifications of code all over the place. Sequential if/if else statements might see a decline, and there would be far less repetition of terms in the conditional statements. If switch (or something like it) were massaged to be as nice to use as foreach is, I think you'll find it will be used all over the place. Note: I probably wouldn't be exaggerating if I said foreach is the main reason I started looking into D in the first place. When I first glanced over the D feature list, I could have easily closed the browser tab, but that's the thing that kept me reading... I've said it before, and I'll say it again, I think these things are _so fundamental_, that their importance is often underestimated, and often overlooked. Could you imagine D without foreach? In retrospect, you can't. But If you were arguing from a position where you never had anything like foreach to the value of it's inclusion, it wouldn't look anywhere near as strong as it does in retrospect. The idea of eliminating many unsightly if/else if blocks is very appealing to me. Just scanning through my code, I can imagine so many instances where my code would become more readable. People usually use switch today for the same reason, but it's always a hard call... is the crappiness of 'switch' a quantifiable improvement over the if/else if sequence? I find myself asking that question all the time. That's why I brought it up.I think a really useful construct could be made out of switch, but it seems that it won't happen because it must support C code unchanged.I tend to agree with Andrei on this - the proposals aren't fundamental or game changing, and are kinda just bouncing the rubble around (po-tay-to vs po-tah-to).Isn't that the entire point of final switch?But... that's like making it an error for an if() to appear without an else statement. It's _exactly_ like that. I don't think I couldn't disagree more. Imagine: if(condition) { doSomething(); } else {} blah blah. if(failed) { handleError(); } else {}Why introduce final switch to address that, then do this aswell?Implicit in your questions is switches will only be used on enums, i.e. all the values a type can be are known to the compiler. This is only true for a smallish subset of types that are switched on. final switch : for enums default : for everything else
Feb 17 2014
On 2/17/2014 5:49 AM, Manu wrote:Refer to my other reply wrt the 'rubble' concept.Sure :-)I think a quality implementation would be fairly game changing. A properly scoped and fully featured switch/select/match statement would result in some radical simplifications of code all over the place.I have a real hard time seeing the proposed changes as radical or game changing.If switch (or something like it) were massaged to be as nice to use as foreach is, I think you'll find it will be used all over the place.foreach() is quite a large improvement, because by abstracting away the mechanics of iteration, code need no longer be aware of just what abstract type is being looped over. Furthermore, it eliminates several common sources of coding bugs. I'm not seeing this with changes in switch.
Feb 17 2014
On 18 February 2014 05:51, Walter Bright <newshound2 digitalmars.com> wrote:On 2/17/2014 5:49 AM, Manu wrote:I think abstracting away volumes of comparative matching logic is similarly interesting to eliminating tedious iteration logic. I find out-by-ones and bogus comparisons that I didn't spot is a very common class of bug (often just because matching code is long and repetitive). Cut and paste, oops; you didn't spot that <= is actually >= from where you cut... or you didn't see it because the line is so long with repetition of the terms being compared that it's run off the right edge. *disclaimer: peoples experiences may differ, this is my experience. I agree, it's probably not as game-changing as foreach, but I think if you had it for a few years and became accustomed to writing much of that comparative logic in a simple and really obvious/less-repetitive way, you'd look back and wonder how you did without it. I suspect it's possible that the repetitive matching logic often found in if() statements represent a lot more code by volume than the iteration logic eliminated by foreach ever did in for loops. I can't say how big a deal it is until I make a habit of applying it everywhere, but I can imagine the potential for massive improvement in readability, and elimination of many long if() expressions. Comparing the savings: for(int i=0; i<things.length; ++i) -> foreach(i, thing; things) if(thing.member >= min && thing.member < max) -> match(thing.member) case(min..max) If an 'else if' appears, the savings compound considerably. I'm a practicality motivated programmer, I don't dream about futuristic features as much as I respond to the things that annoy me consistently on a daily basis. I don't like friction between me and getting my work done, and it's the little things that come up most often that tend to really bug me. I'd like to think the languages foundational keywords should offer a good experience. You'll be typing them over and over again from now until the day you die. Looking at other languages, I think there's clearly a missed opportunity to do something a lot more modern and useful with the switch concept. Rust does it nice. It's got a nice functional flavour to it.Refer to my other reply wrt the 'rubble' concept.Sure :-) I think a quality implementation would be fairly game changing. A properlyscoped and fully featured switch/select/match statement would result in some radical simplifications of code all over the place.I have a real hard time seeing the proposed changes as radical or game changing. If switch (or something like it) were massaged to be as nice to use asforeach is, I think you'll find it will be used all over the place.foreach() is quite a large improvement, because by abstracting away the mechanics of iteration, code need no longer be aware of just what abstract type is being looped over. Furthermore, it eliminates several common sources of coding bugs. I'm not seeing this with changes in switch.
Feb 17 2014
On 2/16/2014 10:39 PM, Manu wrote:Yeah, but when I suggest a..b, I suggest applying existing [) range rules, as would be expected. It doesn't make sense for enum keys, and I think the existing syntax is acceptable for [] usage with enum keys, but you're not always switching on enums. Perhaps supporting both would be useful, where a..b is [) as expected, and 'case A: .. case B:' is [] for use with enums?There was a HUGE debate on all this back when the feature was first added, and every miniscule possibility and detail was thoroughly examined and argued ad nauseam. IIRC, I was actually one the people not real happy with the syntax we have, but the thing is, it really isn't a big deal. It's just syntactical details on one particular construct. Yea, switch could be nicer looking, and it's not one of the nicer parts of D syntax, but the semantics are reasonably solid and that's the important part. The rest is just details and bikeshedding. Personally, I would LOVE to see Nemerle's match statement/expression get into D, but other than that, out of all the tasks D faces, the switch syntax is pretty bottom-rung on both the importance and significance scales.
Feb 17 2014
On 2/16/14, 5:03 PM, Walter Bright wrote:On 2/16/2014 7:42 AM, Manu wrote:Could you show an example of such scenario? I don't get it.3. Why is 'default' necessary? If I'm not switching on an enumerated type, then many values are meaningless. requiring an empty 'default: break;' line at the end is annoying and noisy.It originally was not required, but there was a campaign by a lot of D users to make it required to deal with the common bug of adding a value in one switch statement but forgetting to add it to another corresponding one.
Feb 17 2014
On 2/17/2014 5:48 AM, Ary Borenszweig wrote:On 2/16/14, 5:03 PM, Walter Bright wrote:Having a set of bit flags, and adding another bit flag later, and failing to account for that in existing switch statements.It originally was not required, but there was a campaign by a lot of D users to make it required to deal with the common bug of adding a value in one switch statement but forgetting to add it to another corresponding one.Could you show an example of such scenario? I don't get it.
Feb 17 2014
On 2/17/14, 7:31 PM, Walter Bright wrote:On 2/17/2014 5:48 AM, Ary Borenszweig wrote:auto bit_flag = ...; switch(bit_flag) { case old_bit_flag_1: // do something break; case old_bit_flag_2: // do something break; default: break; } Now suppose bit_flag can get an additional "new_bit_flag" value. How does "default" helps me notice that I'm supposed to add it to that switch statement? I still can't see your point :-( Maybe I need some more example code to understand it.On 2/16/14, 5:03 PM, Walter Bright wrote:Having a set of bit flags, and adding another bit flag later, and failing to account for that in existing switch statements.It originally was not required, but there was a campaign by a lot of D users to make it required to deal with the common bug of adding a value in one switch statement but forgetting to add it to another corresponding one.Could you show an example of such scenario? I don't get it.
Feb 17 2014
On 2/17/2014 2:43 PM, Ary Borenszweig wrote:Now suppose bit_flag can get an additional "new_bit_flag" value. How does "default" helps me notice that I'm supposed to add it to that switch statement?Because if you account for all the cases, you write: default: assert(0); Now you intentionally tell the user that you intentionally covered all the cases.
Feb 17 2014
On Mon, 17 Feb 2014 18:01:38 -0500, Walter Bright <newshound2 digitalmars.com> wrote:On 2/17/2014 2:43 PM, Ary Borenszweig wrote:Would it not be better to infer this, and you could override it by doing default: break;? If that's the "right way", then it should be the default way. I agree with Ary. Sequence will go as follows: Programmer: switch(x) { case 1: statement; break; } Compiler: no no no, you need a default case! Programmer: "Oh fine!" switch(x) { case 1: statement; break; default: break; } How is this advantageous? It just seems annoying... -SteveNow suppose bit_flag can get an additional "new_bit_flag" value. How does "default" helps me notice that I'm supposed to add it to that switch statement?Because if you account for all the cases, you write: default: assert(0); Now you intentionally tell the user that you intentionally covered all the cases.
Feb 17 2014
On 2/17/2014 6:17 PM, Steven Schveighoffer wrote:How is this advantageous? It just seems annoying...Because it makes the programmer's intent clear - are all the cases accounted for, or are there defaults? Of course, no compiler can make you write correct code. But if you're going to write a default anyway, odds are you'll choose the right one.
Feb 17 2014
On Mon, 17 Feb 2014 22:53:15 -0500, Walter Bright <newshound2 digitalmars.com> wrote:On 2/17/2014 6:17 PM, Steven Schveighoffer wrote:I think your anecdotal experience with exception specification in Java is at odds with this expectation. We all know programmers who are faced with seemingly annoyance hoops to jump through jump through them with the least possible effort. -SteveHow is this advantageous? It just seems annoying...Because it makes the programmer's intent clear - are all the cases accounted for, or are there defaults? Of course, no compiler can make you write correct code. But if you're going to write a default anyway, odds are you'll choose the right one.
Feb 18 2014
On 2/18/14, 11:56 AM, Steven Schveighoffer wrote:On Mon, 17 Feb 2014 22:53:15 -0500, Walter Bright <newshound2 digitalmars.com> wrote:Exactly. Programmers will just put "default: break" because of this annoyance without thinking too much if it should be this or assert(0). I think that "final switch" should have the function of checking that you covered all cases, be it with a default case or not.On 2/17/2014 6:17 PM, Steven Schveighoffer wrote:I think your anecdotal experience with exception specification in Java is at odds with this expectation. We all know programmers who are faced with seemingly annoyance hoops to jump through jump through them with the least possible effort. -SteveHow is this advantageous? It just seems annoying...Because it makes the programmer's intent clear - are all the cases accounted for, or are there defaults? Of course, no compiler can make you write correct code. But if you're going to write a default anyway, odds are you'll choose the right one.
Feb 18 2014
On 2/18/2014 7:45 AM, Ary Borenszweig wrote:I think that "final switch" should have the function of checking that you covered all cases,That's just what it does.be it with a default case or not.final is meaningless with a default.
Feb 18 2014
On Tuesday, 18 February 2014 at 15:45:31 UTC, Ary Borenszweig wrote:Exactly. Programmers will just put "default: break" because of this annoyance without thinking too much if it should be this or assert(0). I think that "final switch" should have the function of checking that you covered all cases, be it with a default case or not.A better warning/error message may help here. Please have a look at this PR: https://github.com/D-Programming-Language/dmd/pull/3287
Feb 19 2014
"Steven Schveighoffer" wrote in message news:op.xbhfr5kreav7ka stevens-macbook-pro.local...It's not really the same, because silencing checked exceptions results in a solution that is worse than not having checked exceptions at all. Here if the programmer takes the 'easy route' and sticks in a "default: break;" they're just getting the old behavior back.Of course, no compiler can make you write correct code. But if you're going to write a default anyway, odds are you'll choose the right one.I think your anecdotal experience with exception specification in Java is at odds with this expectation. We all know programmers who are faced with seemingly annoyance hoops to jump through jump through them with the least possible effort.
Feb 18 2014
On Tue, 18 Feb 2014 11:11:36 -0500, Daniel Murphy <yebbliesnospam gmail.com> wrote:"Steven Schveighoffer" wrote in message news:op.xbhfr5kreav7ka stevens-macbook-pro.local...My point though, is that the change to require default gains you nothing except annoyed programmers. Why put it in? I see your point that the difference between ignored exceptions and pass-through exceptions is a lot different than breaking by default on a switch statement. But I wasn't trying to make that comparison, just using it as an example of what programmers do. The comparison I AM making is that we are implementation a requirement that will not achieve the behavior goal it sets out to achieve. -SteveIt's not really the same, because silencing checked exceptions results in a solution that is worse than not having checked exceptions at all. Here if the programmer takes the 'easy route' and sticks in a "default: break;" they're just getting the old behavior back.Of course, no compiler can make you write correct code. But if you're going to write a default anyway, odds are you'll choose the right one.I think your anecdotal experience with exception specification in Java is at odds with this expectation. We all know programmers who are faced with seemingly annoyance hoops to jump through jump through them with the least possible effort.
Feb 18 2014
On Tue, 18 Feb 2014 11:38:41 -0500, Steven Schveighoffer <schveiguy yahoo.com> wrote:The comparison I AM making is that we are implementation a requirement that will not achieve the behavior goal it sets out to achieve.*implementing*, not implementation :) -Steve
Feb 18 2014
"Steven Schveighoffer" wrote in message news:op.xbhkirppeav7ka stevens-macbook-pro.local...My point though, is that the change to require default gains you nothing except annoyed programmers. Why put it in?It only gains you nothing if you respond to the error by mindlessly putting a default: break; in. The compiler is trying to help you by getting you to take an extra second and explicitly state what you what. If you are automatically silencing the error without thinking about the semantics you want, you absolutely should be irritated, but the compiler is not the one doing something stupid here. The awful part of checked exceptions comes from two place IMO - the ide gives you a very very easy way to do thing wrong thing (two clicks IIRC), and doing the right thing is often very very difficult (change exception lists on every calling functions). Here the right and wrong choice are about equal difficulty - trivial. I think complaints about typing those extra couple dozen keystrokes are on the same level as "why do I have to put these ';'s everywhere" and "'immutable' has too many letters".
Feb 18 2014
On Tue, 18 Feb 2014 12:26:36 -0500, Daniel Murphy <yebbliesnospam gmail.com> wrote:"Steven Schveighoffer" wrote in message news:op.xbhkirppeav7ka stevens-macbook-pro.local...It may not be mindless. Most people who want to handle the default case do it. It's usually not so much "I didn't think of handling other values," it's more "I never expect other values to come in, go away annoying compiler error."My point though, is that the change to require default gains you nothing except annoyed programmers. Why put it in?It only gains you nothing if you respond to the error by mindlessly putting a default: break; in.Here the right and wrong choice are about equal difficulty - trivial. I think complaints about typing those extra couple dozen keystrokes are on the same level as "why do I have to put these ';'s everywhere" and "'immutable' has too many letters".I think it's the same as saying you have to always have an else clause after an if statement, even if it's "else {}" -Steve
Feb 18 2014
On 2/18/14, 2:52 PM, Steven Schveighoffer wrote:I think it's the same as saying you have to always have an else clause after an if statement, even if it's "else {}"Lol, I swear I didn't read your answer before posting mine.
Feb 18 2014
"Steven Schveighoffer" wrote in message news:op.xbhnw5rbeav7ka stevens-macbook-pro.local...It may not be mindless. Most people who want to handle the default case do it. It's usually not so much "I didn't think of handling other values," it's more "I never expect other values to come in, go away annoying compiler error."So why not put an assert(0) in instead of a break? Tell the compiler that you're assuming there are no other possible values. This is obviously the right thing to do here, and even if you ignore it the compiler _is_ trying to help you.I think it's the same as saying you have to always have an else clause after an if statement, even if it's "else {}"If 'if' was primarily used for the same thing that switch is, this would be perfectly reasonable.
Feb 19 2014
On 2/19/14, 6:42 AM, Daniel Murphy wrote:"Steven Schveighoffer" wrote in message news:op.xbhnw5rbeav7ka stevens-macbook-pro.local...Sometimes you don't care about other values, which is different than not expecting other values. For example: auto a = ...; switch(a) { case 1: a += 1; case 2: a += 2; // In other cases, leave "a" as is }It may not be mindless. Most people who want to handle the default case do it. It's usually not so much "I didn't think of handling other values," it's more "I never expect other values to come in, go away annoying compiler error."So why not put an assert(0) in instead of a break? Tell the compiler that you're assuming there are no other possible values. This is obviously the right thing to do here, and even if you ignore it the compiler _is_ trying to help you.
Feb 19 2014
On Wednesday, 19 February 2014 at 14:14:01 UTC, Ary Borenszweig wrote:On 2/19/14, 6:42 AM, Daniel Murphy wrote:Just put default: break instead of that comment, it's shorter that way:P"Steven Schveighoffer" wrote in message news:op.xbhnw5rbeav7ka stevens-macbook-pro.local...Sometimes you don't care about other values, which is different than not expecting other values. For example: auto a = ...; switch(a) { case 1: a += 1; case 2: a += 2; // In other cases, leave "a" as is }It may not be mindless. Most people who want to handle the default case do it. It's usually not so much "I didn't think of handling other values," it's more "I never expect other values to come in, go away annoying compiler error."So why not put an assert(0) in instead of a break? Tell the compiler that you're assuming there are no other possible values. This is obviously the right thing to do here, and even if you ignore it the compiler _is_ trying to help you.
Feb 19 2014
On Wed, 19 Feb 2014 09:17:58 -0500, QAston <qaston gmail.com> wrote:On Wednesday, 19 February 2014 at 14:14:01 UTC, Ary Borenszweig wrote:I think the comment was meant as an explanation to you, not something that would actually be in the code :) -Steveauto a = ...; switch(a) { case 1: a += 1; case 2: a += 2; // In other cases, leave "a" as is }Just put default: break instead of that comment, it's shorter that way:P
Feb 20 2014
On Wed, 19 Feb 2014 04:42:19 -0500, Daniel Murphy <yebbliesnospam gmail.com> wrote:"Steven Schveighoffer" wrote in message news:op.xbhnw5rbeav7ka stevens-macbook-pro.local...Putting default: assert(0); changes the meaning of the code. In other words: switch(x) { case 1: ... } is the same as: switch(x) { case 1: ... default: break; } You are keeping the code the same. I don't think people would think of adding the assert(0), I wouldn't. And as Ary pointed out, it may be that you expect the default to occur, but don't want to do anything.It may not be mindless. Most people who want to handle the default case do it. It's usually not so much "I didn't think of handling other values," it's more "I never expect other values to come in, go away annoying compiler error."So why not put an assert(0) in instead of a break? Tell the compiler that you're assuming there are no other possible values. This is obviously the right thing to do here, and even if you ignore it the compiler _is_ trying to help you.'if' and 'switch' are commonly used interchangeably. Frequently one uses 'switch' where they would normally use 'if' to avoid evaluating something multiple times. -SteveI think it's the same as saying you have to always have an else clause after an if statement, even if it's "else {}"If 'if' was primarily used for the same thing that switch is, this would be perfectly reasonable.
Feb 20 2014
"Steven Schveighoffer" wrote in message news:op.xbk5cxeoeav7ka stevens-macbook-pro.local...Putting default: assert(0); changes the meaning of the code. In other words: switch(x) { case 1: ... } is the same as: switch(x) { case 1: ... default: break; } You are keeping the code the same. I don't think people would think of adding the assert(0), I wouldn't.Are we talking about writing new code or porting C/C++ code? If the latter, I agree there is a high chance of just copy-pasting in a default: break; everywhere the error pops up.And as Ary pointed out, it may be that you expect the default to occur, but don't want to do anything.Sure, and you know this when you write the code and choose the correct one.'if' and 'switch' are commonly used interchangeably. Frequently one uses 'switch' where they would normally use 'if' to avoid evaluating something multiple times.I'm not sure this is true, at least not in my code.
Feb 20 2014
On 2/18/14, 2:26 PM, Daniel Murphy wrote:"Steven Schveighoffer" wrote in message news:op.xbhkirppeav7ka stevens-macbook-pro.local...The compiler should force you to write an "else" for every if then: if (a == 2) { // do something } Error: missing else if (a == 2) { // do something } else { nothing; } Or maybe: if (a == 2) { // do something } else { assert(0); } I think the main complaint is that if you refactor a chain of if/else-if into a switch statement, then you have to add a "default: break;" for sure, which is just redundant.My point though, is that the change to require default gains you nothing except annoyed programmers. Why put it in?It only gains you nothing if you respond to the error by mindlessly putting a default: break; in. The compiler is trying to help you by getting you to take an extra second and explicitly state what you what. If you are automatically silencing the error without thinking about the semantics you want, you absolutely should be irritated, but the compiler is not the one doing something stupid here. The awful part of checked exceptions comes from two place IMO - the ide gives you a very very easy way to do thing wrong thing (two clicks IIRC), and doing the right thing is often very very difficult (change exception lists on every calling functions). Here the right and wrong choice are about equal difficulty - trivial. I think complaints about typing those extra couple dozen keystrokes are on the same level as "why do I have to put these ';'s everywhere" and "'immutable' has too many letters".
Feb 18 2014
On 2/18/2014 8:38 AM, Steven Schveighoffer wrote:My point though, is that the change to require default gains you nothing except annoyed programmers. Why put it in?This was fiercely debated at length and settled here years ago. It isn't going to change.The comparison I AM making is that we are implementation a requirement that will not achieve the behavior goal it sets out to achieve.It's been this way for years now, if there was emergent bad behavior, it would be obvious by now. But I haven't heard any reports of such.
Feb 18 2014
On Tue, 18 Feb 2014 17:37:43 -0500, Walter Bright <newshound2 digitalmars.com> wrote:On 2/18/2014 8:38 AM, Steven Schveighoffer wrote:I thought it was a more recent change than years ago. When was the change made? Looking it up, looks like 2011. That was a long time ago, longer than I thought.My point though, is that the change to require default gains you nothing except annoyed programmers. Why put it in?This was fiercely debated at length and settled here years ago. It isn't going to change.Emergent bad behavior is not the result I would expect. Most likely, leaving out the default case was not an error. If this fixed a "bug" that didn't exist, the fact that bad behavior didn't result isn't really informative. What I really would be curious about is if in most D code, you see a lot more default: break; than default: assert(0); In any case, I am not vehemently against requiring a default case, it's not terrible to put in default: break; I just find it somewhat puzzling that it's required. -SteveThe comparison I AM making is that we are implementation a requirement that will not achieve the behavior goal it sets out to achieve.It's been this way for years now, if there was emergent bad behavior, it would be obvious by now. But I haven't heard any reports of such.
Feb 20 2014
Steven Schveighoffer:What I really would be curious about is if in most D code, you see a lot more default: break; than default: assert(0);I have written tons of D2 code in the last years, and such "default: assert(0);" is quite uncommon in my code. Probably less than 8-10 usages in the whole code base. Bye, bearophile
Feb 20 2014
On Thu, 20 Feb 2014 10:08:48 -0500, bearophile <bearophileHUGS lycos.com> wrote:Steven Schveighoffer:But what about default: break;? -SteveWhat I really would be curious about is if in most D code, you see a lot more default: break; than default: assert(0);I have written tons of D2 code in the last years, and such "default: assert(0);" is quite uncommon in my code. Probably less than 8-10 usages in the whole code base.
Feb 20 2014
"Steven Schveighoffer" wrote in message news:op.xbk44onleav7ka stevens-macbook-pro.local...What I really would be curious about is if in most D code, you see a lot more default: break; than default: assert(0);I just did a quick git-grep on the compiler source (not D, but all switches do have a default thanks to the d port) With 707 "default:"s 68 had a break on either the same or next line, and 249 had an assert(0). On phobos I get 22 assert(0)s vs 10 breaks with 147 defaults With druntime i get 24 assert(0)s + 5 error();s vs 11 breaks with 64 defaults.
Feb 20 2014
On Thu, 20 Feb 2014 10:13:27 -0500, Daniel Murphy <yebbliesnospam gmail.com> wrote:"Steven Schveighoffer" wrote in message news:op.xbk44onleav7ka stevens-macbook-pro.local...Good data, but I was more thinking of people who use D, not the core language. The core language's developers have different behaviors than standard users. I'm not dismissing this data, but I would like to see more application statistics. Another interesting data point would be whether any of those asserts were inserted after the language deprecated missing defaults, or if they existed beforehand. One thing that is nice is how asserts are supported in D. It makes this a much easier decision. -SteveWhat I really would be curious about is if in most D code, you see a lot more default: break; than default: assert(0);I just did a quick git-grep on the compiler source (not D, but all switches do have a default thanks to the d port) With 707 "default:"s 68 had a break on either the same or next line, and 249 had an assert(0). On phobos I get 22 assert(0)s vs 10 breaks with 147 defaults With druntime i get 24 assert(0)s + 5 error();s vs 11 breaks with 64 defaults.
Feb 20 2014
On 21 February 2014 01:20, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Thu, 20 Feb 2014 10:13:27 -0500, Daniel Murphy < yebbliesnospam gmail.com> wrote: "Steven Schveighoffer" wrote in message news:op.xbk44onleav7kaIn my little app: 17 default: break; 1 default: assert(0); ... and I just realised it should have been a final switch() anyway... so now there's 0. I haven't just been lazy, the default case just happens to be as if an unhandled else in many cases. Another interesting data point would be whether any of those asserts werestevens-macbook-pro.local... What I really would be curious about is if in most D code, you see a lotGood data, but I was more thinking of people who use D, not the core language. The core language's developers have different behaviors than standard users. I'm not dismissing this data, but I would like to see more application statistics.more default: break; than default: assert(0);I just did a quick git-grep on the compiler source (not D, but all switches do have a default thanks to the d port) With 707 "default:"s 68 had a break on either the same or next line, and 249 had an assert(0). On phobos I get 22 assert(0)s vs 10 breaks with 147 defaults With druntime i get 24 assert(0)s + 5 error();s vs 11 breaks with 64 defaults.inserted after the language deprecated missing defaults, or if they existed beforehand. One thing that is nice is how asserts are supported in D. It makes this a much easier decision. -Steve
Feb 20 2014
On 2/20/14, 1:53 PM, Manu wrote:On 21 February 2014 01:20, Steven Schveighoffer <schveiguy yahoo.com <mailto:schveiguy yahoo.com>> wrote: On Thu, 20 Feb 2014 10:13:27 -0500, Daniel Murphy <yebbliesnospam gmail.com <mailto:yebbliesnospam gmail.com>> wrote: "Steven Schveighoffer" wrote in message news:op.xbk44onleav7ka __stevens-macbook-pro.local... What I really would be curious about is if in most D code, you see a lot more default: break; than default: assert(0); I just did a quick git-grep on the compiler source (not D, but all switches do have a default thanks to the d port) With 707 "default:"s 68 had a break on either the same or next line, and 249 had an assert(0). On phobos I get 22 assert(0)s vs 10 breaks with 147 defaults With druntime i get 24 assert(0)s + 5 error();s vs 11 breaks with 64 defaults. Good data, but I was more thinking of people who use D, not the core language. The core language's developers have different behaviors than standard users. I'm not dismissing this data, but I would like to see more application statistics. In my little app: 17 default: break; 1 default: assert(0); ... and I just realised it should have been a final switch() anyway... so now there's 0.Did you put those "default: break;" because: 1. The compiler told it to do so. 2. You already know the compiler will tell you, so you put it before that happens. In the cases where it was "1.", did it make you think whether you needed to handle the default case?
Feb 20 2014
On 21 February 2014 03:27, Ary Borenszweig <ary esperanto.org.ar> wrote:On 2/20/14, 1:53 PM, Manu wrote:Because the compiler told me. It's not a habit of mine to type it. In the cases where it was "1.", did it make you think whether you needed toOn 21 February 2014 01:20, Steven Schveighoffer <schveiguy yahoo.com <mailto:schveiguy yahoo.com>> wrote: On Thu, 20 Feb 2014 10:13:27 -0500, Daniel Murphy <yebbliesnospam gmail.com <mailto:yebbliesnospam gmail.com>> wrote: "Steven Schveighoffer" wrote in message news:op.xbk44onleav7ka __stevens-macbook-pro.local... What I really would be curious about is if in most D code, you see a lot more default: break; than default: assert(0); I just did a quick git-grep on the compiler source (not D, but all switches do have a default thanks to the d port) With 707 "default:"s 68 had a break on either the same or next line, and 249 had an assert(0). On phobos I get 22 assert(0)s vs 10 breaks with 147 defaults With druntime i get 24 assert(0)s + 5 error();s vs 11 breaks with 64 defaults. Good data, but I was more thinking of people who use D, not the core language. The core language's developers have different behaviors than standard users. I'm not dismissing this data, but I would like to see more application statistics. In my little app: 17 default: break; 1 default: assert(0); ... and I just realised it should have been a final switch() anyway... so now there's 0.Did you put those "default: break;" because: 1. The compiler told it to do so. 2. You already know the compiler will tell you, so you put it before that happens.handle the default case?Never. If I meant to handle the case, I would have already handled the case. I've never forgotten to handle the case when I was supposed to. In the same way I've never forgotten to write else after an if when I intend to.
Feb 20 2014
On 18 February 2014 09:01, Walter Bright <newshound2 digitalmars.com> wrote:On 2/17/2014 2:43 PM, Ary Borenszweig wrote:I think 'final switch' should do that for you, and by typing final, you've intentionally covered the case. There's no room for mistake then.Now suppose bit_flag can get an additional "new_bit_flag" value. How does "default" helps me notice that I'm supposed to add it to that switch statement?Because if you account for all the cases, you write: default: assert(0); Now you intentionally tell the user that you intentionally covered all the cases.
Feb 17 2014
On 2/17/2014 6:38 PM, Manu wrote:I think 'final switch' should do that for you, and by typing final, you've intentionally covered the case. There's no room for mistake then.That's why a default case is not allowed for a 'final' switch.
Feb 17 2014
On 18 February 2014 08:31, Walter Bright <newshound2 digitalmars.com> wrote:On 2/17/2014 5:48 AM, Ary Borenszweig wrote:It sounds like that's basically the same as final switch, just without the enum key to communicate the strong concept. If I were to imagine a solution to that problem I would have also applied final switch, but in the case it's dealing with integers and not enums and therefore can't know which values are valid and tell you that you missed one, it should insert an implicit 'default: assert(0);' (since final switch isn't meant to have 'default' cases), this way any case you don't explicitly handle is considered invalid, and you'll catch your mistake immediately. I expect final switch on enum's must do this anyway (at least in debug)? It's possible to receive a value that's not a recognised enum key; what happens in that case? It seems effectively the same to me.On 2/16/14, 5:03 PM, Walter Bright wrote:Having a set of bit flags, and adding another bit flag later, and failing to account for that in existing switch statements.It originally was not required, but there was a campaign by a lot of D users to make it required to deal with the common bug of adding a value in one switch statement but forgetting to add it to another corresponding one.Could you show an example of such scenario? I don't get it.
Feb 17 2014
On 2/17/2014 6:35 PM, Manu wrote:If I were to imagine a solution to that problem I would have also applied final switch, but in the case it's dealing with integers and not enums and therefore can't know which values are valid and tell you that you missed one, it should insert an implicit 'default: assert(0);' (since final switch isn't meant to have 'default' cases), this way any case you don't explicitly handle is considered invalid, and you'll catch your mistake immediately. I expect final switch on enum's must do this anyway (at least in debug)? It's possible to receive a value that's not a recognised enum key; what happens in that case? It seems effectively the same to me.The 'final' works as you propose. Why not give it a whirl?
Feb 17 2014
On 2/16/14, 7:42 AM, Manu wrote:So D offers great improvements to switch(), but there are a few small things I wonder about.TL;DR of my answer to this: at some point we must get used to the notion that minute syntax tweaks are always possible that make us feel we're making progress when instead we're just moving the rubble around.1. case fall-through is not supported; explicit 'goto case n;' is required. With this in mind, 'break' is unnecessary. Why is it required? It could be implicit upon reaching the next case label, or a scope could be used (with support for omitting the scope for single statements as with if). It's really noisy, and annoying to write everywhere.Implicit fall-through has been specifically eliminated from the language at my behest. I think it is a fine language change. Use "goto case;" to clarify to the maintainer (and incidentally the compiler) you want a fall-through.2. 'case 1, 3, 7, 8:' is awesome! ...but ranged cases have a totally different syntax: 'case 1: .. case 3:' Why settle on that syntax? The inconsistency looks kinda silly when they appear together in code. Surely it's possible to find a syntax that works without repeating case and ':'?There's no inconsistency. The case is not identical with "foreach (a .. b)" or arr[a .. b], both of which don't include b in the explored range. The fact that "case b:" is present is very telling "b" will be acted upon.It's also weird, because it seems that 'case n: .. case m:' is inclusive of m. This may be unexpected.It's expected.I'm not sure it's reasonable to use the '..' syntax in this case for that reason. '..' is an [) range, case ranges must be [] so that it makes sense when dealing with enum key ranges.No.3. Why is 'default' necessary? If I'm not switching on an enumerated type, then many values are meaningless. requiring an empty 'default: break;' line at the end is annoying and noisy.Explicit is better than implicit.I often find myself tempted to rewrite blocks of successive if() logic comparing integers against values/ranges, but it looks silly since the scope rules are not explicit, and 'default: break;' always wastes an extra line.Write the line.I like to reduce noise in my code, and these switch semantics threaten to simplify a lot of code, if not for these strange decisions (purely for legacy compliance?).I think the current switch statement design is a fine design all things considered (compatibility, law of least surprise, usability, readability).Let's consider an example: Code like this: int difficulty = -1; if(e.note.note >= 60 && e.note.note < 72) difficulty = 0; else if(e.note.note >= 72 && e.note.note < 84) difficulty = 1; else if(e.note.note >= 84 && e.note.note < 96) difficulty = 2; else if(e.note.note >= 96 && e.note.note < 108) difficulty = 3; The repetition of e.note.note is annoying, and particular choice of comparisons are liable to result in out-by-ones. It's not nice code to read.For every proposed tweak there will be an example that makes it look great.Rewrites like this: int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; } That's horrid, it's much longer! And there are pointless wasted lines everywhere. The default case is a total waste, since -1 should just be assigned when initialising the variable above.But you'd be wasting an extra assignment. I recall you're one for efficiency.We can compact it a bit like this: int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; } But that's horrible too.The quality of being horrible is in the eye of the beholder. I find this code entirely reasonable.It's not clear what vertical offset the 'break' statements shoudl appear at (I hate stacking up multiple statements across the same line!). The the default case is still a waste.Just do it.Ideally: int difficulty = -1; switch(e.note.note) { case 60 .. 72: difficulty = 0; case 72 .. 84: difficulty = 1; case 84 .. 96: difficulty = 2; case 96 .. 108: difficulty = 3; }Nope.'break's are unnecessary since fallthrough isn't allowed.Silently change the semantics of C code is not something we entertain doing.Proper numeric range could be supported (assuming [) intervals). 'default' case is unnecessary, and removed. The switch and braces results in 3 extra lines, but I still feel this level of simplification results in code that is MUCH more readable than the sequence of if's I started with. It's super obvious what's going on. I have quite many blocks like this. A great man once (actually, frequently) said "If it doesn't look right, it probably isn't".The thing is you can apply that to everything, and justify every tweak, because what looks right is subjective. Andrei
Feb 16 2014
On 17 February 2014 16:18, Andrei Alexandrescu < SeeWebsiteForEmail erdani.org> wrote:On 2/16/14, 7:42 AM, Manu wrote:OT: Do you realise how harsh your posts often appear to people? I often find I need to restrain myself when replying to your blunt dismissals of peoples opinions/suggestions. So, you admit that this is a disaster site, but are reluctant to consider what good may come of it? I'm not suggesting to move the rubble around a bit, I'm suggesting a missed opportunity to build something new and useful from the rubble. There are like, 5 control statements in the language; if, for, while, foreach, switch. To trivialise their importance is surprising. switch is basically the same in D as in C, which kinda finds a purpose here and there, but it's built on a rubbish foundation. I can imagine switch (or something like it) being _extremely_ useful to address whole new classes of problems (like match in rust and others) if it were just a little bit less shit. And it is shit, it's barely better than C; it's verbose, nobody knows how to format 'case' statements, it always seems to violate formatting standards whenever it's used (disagrees with all code everywhere else), programmers always seem to disagree on how it should be. In my opinionated opinion, it always seems to look ugly, and unnecessarily verbose. The ugliness of the syntax makes it an unattractive choice for application to many problems where it may have otherwise been applicable, simplifying code, and making the code more readable and understandable at a glance. The switch statement was obviously initially designed to improve clarity; anything that can be done with a switch statement can easily be done with a series of if's (if you love squinting at comparative conditions and constant repetition of the terms being compared), and it probably did improve clarity, in 1970's... But I think we could do much better, and offer an interesting and useful construct that could be used to clarify code in far more locations than it ever sees use today. 1.So D offers great improvements to switch(), but there are a few small things I wonder about.TL;DR of my answer to this: at some point we must get used to the notion that minute syntax tweaks are always possible that make us feel we're making progress when instead we're just moving the rubble around.It's a patch on a broken design. If switch used proper scoping rules like everything else, nobody would have ever thought that was a reasonable idea. To be clear, perhaps I didn't explain myself clearly; I'm not arguing with the decision about fall-through. I agree that fall-through should be an explicit request. I'm suggesting that in the context of D, where fallthrough is not supported (I offer you congratulations for getting that one in), then 'break;' is entirely pointless, and shouldn't be required. I understand the counter argument to be that "if I paste C code into my D code, there's a potential fail!". And my response is, I think it's lame to gimp D because a language designed 45 years ago had a crappy design. The solution is probably to leave switch as is, and introduce a replacement that's better. 2.case fall-through is not supported; explicit 'goto case n;' is required. With this in mind, 'break' is unnecessary. Why is it required? It could be implicit upon reaching the next case label, or a scope could be used (with support for omitting the scope for single statements as with if). It's really noisy, and annoying to write everywhere.Implicit fall-through has been specifically eliminated from the language at my behest. I think it is a fine language change. Use "goto case;" to clarify to the maintainer (and incidentally the compiler) you want a fall-through.I never suggested a..b used in a switch should be inclusive. I was just commenting on the choice to use '..' at all. I have said elsewhere that I agree '..' should indeed be exclusive, just like everywhere else. I think the existing syntax is useful for enums, and could remain. Perhaps both should be supported? It's also weird, because it seems that 'case n: .. case m:' is inclusive'case 1, 3, 7, 8:' is awesome! ...but ranged cases have a totally different syntax: 'case 1: .. case 3:' Why settle on that syntax? The inconsistency looks kinda silly when they appear together in code. Surely it's possible to find a syntax that works without repeating case and ':'?There's no inconsistency. The case is not identical with "foreach (a .. b)" or arr[a .. b], both of which don't include b in the explored range. The fact that "case b:" is present is very telling "b" will be acted upon.How so? It seems logical in the context of case statements, but '..' does something different in every other instance. If I were new to D, and I saw that, I imagine it would be perfectly reasonable for me to be confused. I'm not sure it's reasonable to use the '..' syntax in this case forof m. This may be unexpected.It's expected.No what? 3.that reason. '..' is an [) range, case ranges must be [] so that it makes sense when dealing with enum key ranges.No.No. I often find myself tempted to rewrite blocks of successive if() logicWhy is 'default' necessary? If I'm not switching on an enumerated type, then many values are meaningless. requiring an empty 'default: break;' line at the end is annoying and noisy.Explicit is better than implicit.No, it looks stupid. If there are few enough cases, I'll use if's instead every time. I lose, and the language loses too. I like to reduce noise in my code, and these switch semantics threatencomparing integers against values/ranges, but it looks silly since the scope rules are not explicit, and 'default: break;' always wastes an extra line.Write the line.Well, I disagree. It offers some improvement over the catastrophic design that C gave us almost half a century ago, but it doesn't address the basic un-structured nature of the statement, and deliberately retains all the elements that made it rubbish back when (for compatibility). Compatibility and law of least surprise I'll grant you. Usability and readability, I don't think so. Certainly not compared to competition. I think what's clear though, is in order to not violate the first 2 (which I agree there is merit in maintaining), any improvement to switch would probably need to come in the form of a new structure, like 'match' in rust, or something designed from the ground-up to not suck, 'select' maybe. I concede that switch can't be fixed. Perhaps it should be deprecated instead. So I guess on that note, I'll leave it there, but I still think it's worth consideration. The functionality that switch offers is tremendously useful, and it would be so much more useful if it were cleaned up; people would actually use it, and probably in a whole bunch of new applications. I think you'd see a quick erosion of if/else if sequences if switch was more awesome. Let's consider an example:to simplify a lot of code, if not for these strange decisions (purely for legacy compliance?).I think the current switch statement design is a fine design all things considered (compatibility, law of least surprise, usability, readability).I see lots and lots of these; opportunities for a structure like an advanced switch to make really nice. Rewrites like this:Code like this: int difficulty = -1; if(e.note.note >= 60 && e.note.note < 72) difficulty = 0; else if(e.note.note >= 72 && e.note.note < 84) difficulty = 1; else if(e.note.note >= 84 && e.note.note < 96) difficulty = 2; else if(e.note.note >= 96 && e.note.note < 108) difficulty = 3; The repetition of e.note.note is annoying, and particular choice of comparisons are liable to result in out-by-ones. It's not nice code to read.For every proposed tweak there will be an example that makes it look great.I've never encountered an optimiser that would fail on something so simple. Even on my Amiga. We can compact it a bit like this:int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; } That's horrid, it's much longer! And there are pointless wasted lines everywhere. The default case is a total waste, since -1 should just be assigned when initialising the variable above.But you'd be wasting an extra assignment. I recall you're one for efficiency.Really? Can you point me to the paragraph in the formatting/style guide that talks about appropriate styling for writing multiple statements on the same line? What happened to DRY? It's not clear what vertical offset the 'break'int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; } But that's horrible too.The quality of being horrible is in the eye of the beholder. I find this code entirely reasonable.Nope, I'll use if instead. DRY and all that. I'd rather repeat the term being used for comparison than repeat 'case' and 'break' all over the place. 'if' produces a similar amount of repetition (perhaps less), but results in properly scoped statements, and I know how it should be formatted. Ideally:statements shoudl appear at (I hate stacking up multiple statements across the same line!). The the default case is still a waste.Just do it.Elaborate? 'break's are unnecessary since fallthrough isn't allowed.int difficulty = -1; switch(e.note.note) { case 60 .. 72: difficulty = 0; case 72 .. 84: difficulty = 1; case 84 .. 96: difficulty = 2; case 96 .. 108: difficulty = 3; }Nope.I agree, we'd need to distinguish the fixed version. Proper numeric range could be supported (assuming [) intervals).Silently change the semantics of C code is not something we entertain doing.Are you saying that switch looks pleasing and coherent to you? As compared with all the other flow control statements existing in D, and competitive statements from other languages? Should I start a poll? Perhaps science can tell us if people find it to be regular and pleasant syntactically. Finally, you didn't address the suggestion to allow assignment of the switch condition to a properly scoped variable: switch([x =] expression) ? Some expression results don't have an easily named concept. Performing the expression on a prior line and assigning to a temp often results in some pretty stupid variable names polluting the outer scope. And it's annoying.'default' case is unnecessary, and removed. The switch and braces results in 3 extra lines, but I still feel this level of simplification results in code that is MUCH more readable than the sequence of if's I started with. It's super obvious what's going on. I have quite many blocks like this. A great man once (actually, frequently) said "If it doesn't look right, it probably isn't".The thing is you can apply that to everything, and justify every tweak, because what looks right is subjective.
Feb 17 2014
On 2/17/14, 5:33 AM, Manu wrote:On 17 February 2014 16:18, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org <mailto:SeeWebsiteForEmail erdani.org>> wrote: On 2/16/14, 7:42 AM, Manu wrote: So D offers great improvements to switch(), but there are a few small things I wonder about. TL;DR of my answer to this: at some point we must get used to the notion that minute syntax tweaks are always possible that make us feel we're making progress when instead we're just moving the rubble around. OT: Do you realise how harsh your posts often appear to people? I often find I need to restrain myself when replying to your blunt dismissals of peoples opinions/suggestions.You're right. I shouldn't have answered because now the thread is fueling from the answers it's getting. Well actually I did my best in my post to sugarcoat my opinion of the post, which I found a whine on minor issues and a collection of entirely petty proposals. Sorry. Advanced pattern matching and safe downcasting and such - that may be valuable to discuss. But the concerns expressed in this thread build a store on saving on typing 'case' and 'break'.So, you admit that this is a disaster site, but are reluctant to consider what good may come of it?I didn't admit that. (And I'm sure this is not an attempt to put words in my mouth.) That wasn't even the charge. I'll actually quote this thread's overture: "So D offers great improvements to switch(), but there are a few small things I wonder about."I'm not suggesting to move the rubble around a bit, I'm suggesting a missed opportunity to build something new and useful from the rubble.I believe even if we implement all of these suggestions (change range syntax, "break" no longer required, no need for "default") to perfection, they would have zero consequence on the success of D. I really do believe that.There are like, 5 control statements in the language; if, for, while, foreach, switch. To trivialise their importance is surprising.It would be surprising. But nobody is.switch is basically the same in D as in C, which kinda finds a purpose here and there, but it's built on a rubbish foundation. I can imagine switch (or something like it) being _extremely_ useful to address whole new classes of problems (like match in rust and others) if it were just a little bit less shit.A match statement would be interesting, but was not asked for. This thread wrings hands over punctuation and formatting. [snip some of the said hand wringing]I think the current switch statement design is a fine design all things considered (compatibility, law of least surprise, usability, readability). Well, I disagree. It offers some improvement over the catastrophic design that C gave us almost half a century ago, but it doesn't address the basic un-structured nature of the statement, and deliberately retains all the elements that made it rubbish back when (for compatibility). Compatibility and law of least surprise I'll grant you. Usability and readability, I don't think so. Certainly not compared to competition. I think what's clear though, is in order to not violate the first 2 (which I agree there is merit in maintaining), any improvement to switch would probably need to come in the form of a new structure, like 'match' in rust, or something designed from the ground-up to not suck, 'select' maybe. I concede that switch can't be fixed. Perhaps it should be deprecated instead.I don't think we should deprecate switch. And if the to-be-proposed match/select's main features are small syntactic fixes to switch, I don't think they're worth adding.So I guess on that note, I'll leave it there, but I still think it's worth consideration.Improving on "switch" is hardly the kind of thing that keeps me awake at night. Finalizing the language is. Threads. Garbage. Null pointers. this(this). Allocators. Dynamic libraries. Better punctuation for "switch" is not even down the list - it's not on the list. And I don't think it should. If that is, anything could be put on the list by the loudest voice asking.The functionality that switch offers is tremendously useful, and it would be so much more useful if it were cleaned up; people would actually use it, and probably in a whole bunch of new applications.I don't think so. Again, I think a nicer switch syntax would do zero for the success of D. [snip]Finally, you didn't address the suggestion to allow assignment of the switch condition to a properly scoped variable: switch([x =] expression) ? Some expression results don't have an easily named concept. Performing the expression on a prior line and assigning to a temp often results in some pretty stupid variable names polluting the outer scope. And it's annoying.That bugzilla is a minor improvement that has precedent in the "if" statement, so I'd accept "switch (auto var = expr)" if implemented. Andrei
Feb 17 2014
OT: Do you realise how harsh your posts often appear to people? I often find I need to restrain myself when replying to your blunt dismissals of peoples opinions/suggestions. So, you admit that this is a disaster site, but are reluctant to consider what good may come of it? I'm not suggesting to move the rubble around a bit, I'm suggesting a missed opportunity to build something new and useful from the rubble. There are like, 5 control statements in the language; if, for, while, foreach, switch. To trivialise their importance is surprising. switch is basically the same in D as in C, which kinda finds a purpose here and there, but it's built on a rubbish foundation. I can imagine switch (or something like it) being _extremely_ useful to address whole new classes of problems (like match in rust and others) if it were just a little bit less shit. And it is shit, it's barely better than C; it's verbose, nobody knows how to format 'case' statements, it always seems to violate formatting standards whenever it's used (disagrees with all code everywhere else), programmers always seem to disagree on how it should be. In my opinionated opinion, it always seems to look ugly, and unnecessarily verbose. The ugliness of the syntax makes it an unattractive choice for application to many problems where it may have otherwise been applicable, simplifying code, and making the code more readable and understandable at a glance. The switch statement was obviously initially designed to improve clarity; anything that can be done with a switch statement can easily be done with a series of if's (if you love squinting at comparative conditions and constant repetition of the terms being compared), and it probably did improve clarity, in 1970's... But I think we could do much better, and offer an interesting and useful construct that could be used to clarify code in far more locations than it ever sees use today.And do you realise that every sentence in your post is matter your your persona taste. It is extremely subjective, and you provide no proof that majority of people who are interested in all this share your opinion, do you? Do not get me wrong, I am not defending Andrei here (he can defend himself better than me). It is just shocking sometimes what kind of non-sense is posted here. Let me dodge back few quotes of your post back at you to think about what I said in the paragraph above: 1) "built on a rubbish foundation" 2) "less shit" (no comment here...!) 3) "nobody knows how to format 'case' statements" (well, if you do not know, there are people who do) 4) "The ugliness of the syntax" (again your own taste) If you scan your own post(s), you will find many examples of what I am saying. This attitude of yours won't get you far.
Feb 17 2014
On 18 February 2014 02:48, Dejan Lekic <dejan.lekic gmail.com> wrote:Yes, they're obviously opinions. I wouldn't use phrasing like that if I wasn't trying to demonstrate my strong opinion on the matter. I only raised some details that are annoying me, I didn't say I had any science to show it was a majority opinion. I'm not sure why that's necessary to make an opinion oriented post. A large part of the reason for posting in the first place is to find if/how many people also feel that way. That's the nature of opinions, I don't know what other peoples are until I talk about it. Let me dodge back few quotes of your post back at you to think about what I[snip]And do you realise that every sentence in your post is matter your your persona taste. It is extremely subjective, and you provide no proof that majority of people who are interested in all this share your opinion, do you? Do not get me wrong, I am not defending Andrei here (he can defend himself better than me). It is just shocking sometimes what kind of non-sense is posted here.said in the paragraph above: 1) "built on a rubbish foundation" 2) "less shit" (no comment here...!) 3) "nobody knows how to format 'case' statements" (well, if you do not know, there are people who do) 4) "The ugliness of the syntax" (again your own taste) If you scan your own post(s), you will find many examples of what I am saying. This attitude of yours won't get you far.Well, I firmly stand by all those convictions. They also look worse out of context. I don't think switch is particularly good, and firmly believe C's switch statement was (is) a design catastrophe. I've believed that for 20 years. You're welcome to disagree, and tell me why you do. I might even change my opinion if someone can convince me it's awesome the way it is for some reason. I've spent 3 days basically writing switch statements. I haven't enjoyed it, and I feel the experience is a big missed opportunity.
Feb 17 2014
On 2/17/2014 10:03 AM, Manu wrote:Well, I firmly stand by all those convictions. They also look worse out of context. I don't think switch is particularly good, and firmly believe C's switch statement was (is) a design catastrophe. I've believed that for 20 years. You're welcome to disagree, and tell me why you do. I might even change my opinion if someone can convince me it's awesome the way it is for some reason. I've spent 3 days basically writing switch statements. I haven't enjoyed it, and I feel the experience is a big missed opportunity.Having strong convictions is good, but strong reactions to them come with the territory :-)
Feb 17 2014
On 2/17/2014 5:33 AM, Manu wrote:We can compact it a bit like this: int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; } But that's horrible too.I tend to format such like this: int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; } By lining things up, it takes on a tabular appearance. People are good at inferring patterns, and such tabular arrangements make it easy to spot squeaky wheels.Finally, you didn't address the suggestion to allow assignment of the switch condition to a properly scoped variable: switch([x =] expression) ?That's probably a good idea.
Feb 17 2014
On 18 February 2014 06:00, Walter Bright <newshound2 digitalmars.com> wrote:I tend to format such like this: int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; } By lining things up, it takes on a tabular appearance. People are good at inferring patterns, and such tabular arrangements make it easy to spot squeaky wheels.Me too, but you don't feel this is basically a hack? About half of that text is repeated cruft, and there's no precedent for formatting well-structured code like that anywhere else in the language. How long would you say you spend on average fiddling with the tabulation? I am known to spend minutes pressing the space bar, trying to make it line up and look nice. And then invariably, some other case comes along, with a slightly longer identifier name, and you have to work your way up shifting everything around against with a bunch more spaces.. pollutes source control history, etc. And then that case with the REALLY long identifier name comes along, and you end out with so many spaces surrounding all the other cases, that it becomes difficult to associate which line matches which case, so then you think to yourself, "this one long case is ruining my code, maybe I should break the pattern and fall this long one onto it's own line below...", and then you're just wasting time, pushing the spacebar key, trying to work around something that shouldn't have been an issue in the first place. Often enough the break statements end up far off the right hand side of the screen due to that one long statement in the sequence; do you line them all up religiously far to the right? Or do you make an exception for that one long line, allowing it to span beyond the 'break' line, and keep the rest lined up nearer to the code they terminate? Tell me this doesn't happen to you? Surely I'm not the only one that faces this sort of conundrum frequently when I try and use switch? :) I can't see that practise as anything other than a formatting hack to deal with something that was structurally unsound in the first place.Finally, you didn't address the suggestion to allow assignment of the switch > condition to a properly scoped variable: switch([x =] expression) ? That's probably a good idea.Cool, I'll bugzilla it. At least something useful may comes from my ranting :P
Feb 17 2014
On 2/17/2014 6:54 PM, Manu wrote:Me too, but you don't feel this is basically a hack?I see nothing hackish about it. After all, there's a reason D does not enforce whitespace.About half of that text is repeated cruft, and there's no precedent for formatting well-structured code like that anywhere else in the language. How long would you say you spend on average fiddling with the tabulation? I am known to spend minutes pressing the space bar, trying to make it line up and look nice. And then invariably, some other case comes along, with a slightly longer identifier name, and you have to work your way up shifting everything around against with a bunch more spaces.. pollutes source control history, etc. And then that case with the REALLY long identifier name comes along, and you end out with so many spaces surrounding all the other cases, that it becomes difficult to associate which line matches which case, so then you think to yourself, "this one long case is ruining my code, maybe I should break the pattern and fall this long one onto it's own line below...", and then you're just wasting time, pushing the spacebar key, trying to work around something that shouldn't have been an issue in the first place. Often enough the break statements end up far off the right hand side of the screen due to that one long statement in the sequence; do you line them all up religiously far to the right? Or do you make an exception for that one long line, allowing it to span beyond the 'break' line, and keep the rest lined up nearer to the code they terminate? Tell me this doesn't happen to you? Surely I'm not the only one that faces this sort of conundrum frequently when I try and use switch? :)Shirley you're joking. If that's the hardest problem you face programming in D, I am well satisfied that D is a great design!
Feb 17 2014
On Tuesday, 18 February 2014 at 04:02:35 UTC, Walter Bright wrote:Shirley you're joking. If that's the hardest problem you face programming in D, I am well satisfied that D is a great design!http://www.youtube.com/watch?feature=player_detailpage&v=KM2K7sV-K74#t=5
Feb 17 2014
On 18 February 2014 14:02, Walter Bright <newshound2 digitalmars.com> wrote:Shirley you're joking. If that's the hardest problem you face programming in D, I am well satisfied that D is a great design!I didn't say that. But I do think it's more significant than it appears. If people deliberately avoid a fundamental structure because it's awkward and in many cases it doesn't offer a clarification of their code in practise, when it easily could/should have, I think that's a significant loss. Note; that's a commentary on one criticism relating to one particular pasted block of code wrt switch as it exists right now. It's not a summary of all my thoughts presented in this thread, just a single facet of my post.
Feb 17 2014
On 2/17/2014 9:54 PM, Manu wrote:On 18 February 2014 06:00, Walter Bright <newshound2 digitalmars.com> wrote:I use the formatting posted above, and it takes me very, very little time.I tend to format such like this: int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; } By lining things up, it takes on a tabular appearance. People are good at inferring patterns, and such tabular arrangements make it easy to spot squeaky wheels.Me too, but you don't feel this is basically a hack? About half of that text is repeated cruft, and there's no precedent for formatting well-structured code like that anywhere else in the language. How long would you say you spend on average fiddling with the tabulation?I am known to spend minutes pressing the space bar, trying to make it line up and look nice. And then invariably, some other case comes along, with a slightly longer identifier name, and you have to work your way up shifting everything around against with a bunch more spaces.. pollutes source control history, etc.Sounds like you need elastic tabstops: http://nickgravgaard.com/elastictabstops/ I don't use them personally since PN2 doesn't support them yet, but they're a brilliant idea and they do solve that re-aligning issue. Word processors figured out how tabstops are supposed to work ages ago. Elastic tabstops really just amount to bringing code editors' ancient tab-handling up-to-date with the 90's.And then that case with the REALLY long identifier name comes along, and you end out with so many spaces surrounding all the other cases, that it becomes difficult to associate which line matches which case, so then you think to yourself, "this one long case is ruining my code, maybe I should break the pattern and fall this long one onto it's own line below...", and then you're just wasting time, pushing the spacebar key, trying to work around something that shouldn't have been an issue in the first place. Often enough the break statements end up far off the right hand side of the screen due to that one long statement in the sequence; do you line them all up religiously far to the right? Or do you make an exception for that one long line, allowing it to span beyond the 'break' line, and keep the rest lined up nearer to the code they terminate? Tell me this doesn't happen to you? Surely I'm not the only one that faces this sort of conundrum frequently when I try and use switch? :)Erm, between all of that, plus your strong objection to "default: break;", I really do get the impression you're just simply being very OCD about this stuff. I don't mean that as an insult, I just think it's all a bit "Adrian Monk of source code", if you're familiar with the reference.
Feb 17 2014
On Tuesday, 18 February 2014 at 06:00:25 UTC, Nick Sabalausky wrote:Erm, between all of that, plus your strong objection to "default: break;", I really do get the impression you're just simply being very OCD about this stuff. I don't mean that as an insult, I just think it's all a bit "Adrian Monk of source code", if you're familiar with the reference.I have code formatting OCD. Switch case is an abomination. It looks nice with spaces and all, but anything that can't be identified by an auto formatter should die in a fire. Also, I use arbitrary empty structs in my multi threading code as tokens. The type pattern matching of the mailbox looks nice. Unlike the switch case statements. Tl;dr: Manual indentation, ew. Identically indented } on multiple lines, ew.
Feb 18 2014
On Tuesday, 18 February 2014 at 02:55:10 UTC, Manu wrote:Me too, but you don't feel this is basically a hack? About half of that text is repeated cruft, and there's no precedent for formatting well-structured code like that anywhere else in the language.There are other ways in D to deal with repetition. For people coming from C/C++ some of these tricks are unnatural because programmers writing in those prefer to just write everything "inline" for performance reasons. So, possible sollutions: - go make a function: getDifficulty(int note) { switch(note) { case 60: .. case 71: return 0; case 72: .. case 83: return 1; case 84: .. case 95: return 2; case 96: .. case 107: return 3; default: return -1; } } and then difficulty = getDifficulty(e.note.note); - you can make this function local if it's not needed anywhere, local functions are awesome - they reduce a lot of code duplication. Any code that repeats inside a local scope can be put inside a local function - you can also make e.note a real type with a method instead of inlining the logic in place and call e.note.getDifficulty or whatever If your code is full of switch-cases you should probably use polymorphism instead (virtual dispatch, omg).
Feb 19 2014
2014-02-17 22:33 GMT+09:00 Manu <turkeyman gmail.com>:On 17 February 2014 16:18, Andrei Alexandrescu < SeeWebsiteForEmail erdani.org> wrote:I completely agree with Andrei. We should continue to keep that D is the successor of the most used system languages - C and C++. it's a *huge* advantage against other modern languages. Kenji HaraOn 2/16/14, 7:42 AM, Manu wrote:OT: Do you realise how harsh your posts often appear to people? I often find I need to restrain myself when replying to your blunt dismissals of peoples opinions/suggestions. So, you admit that this is a disaster site, but are reluctant to consider what good may come of it? I'm not suggesting to move the rubble around a bit, I'm suggesting a missed opportunity to build something new and useful from the rubble.So D offers great improvements to switch(), but there are a few small things I wonder about.TL;DR of my answer to this: at some point we must get used to the notion that minute syntax tweaks are always possible that make us feel we're making progress when instead we're just moving the rubble around.
Feb 17 2014
On 18 February 2014 01:02, Kenji Hara <k.hara.pg gmail.com> wrote:2014-02-17 22:33 GMT+09:00 Manu <turkeyman gmail.com>: On 17 February 2014 16:18, Andrei Alexandrescu <I agree, to an extent. That's why I say if it is to be improved, I guess it needs a new name. foreach eliminated almost all instances of for. I don't think anyone's upset about that.SeeWebsiteForEmail erdani.org> wrote:I completely agree with Andrei. We should continue to keep that D is the successor of the most used system languages - C and C++. it's a *huge* advantage against other modern languages.On 2/16/14, 7:42 AM, Manu wrote:OT: Do you realise how harsh your posts often appear to people? I often find I need to restrain myself when replying to your blunt dismissals of peoples opinions/suggestions. So, you admit that this is a disaster site, but are reluctant to consider what good may come of it? I'm not suggesting to move the rubble around a bit, I'm suggesting a missed opportunity to build something new and useful from the rubble.So D offers great improvements to switch(), but there are a few small things I wonder about.TL;DR of my answer to this: at some point we must get used to the notion that minute syntax tweaks are always possible that make us feel we're making progress when instead we're just moving the rubble around.
Feb 17 2014
"Manu" <turkeyman gmail.com> wrote in message news:mailman.156.1392649746.6445.digitalmars-d puremagic.com...I agree, to an extent. That's why I say if it is to be improved, I guess it needs a new name. foreach eliminated almost all instances of for. I don't think anyone's upset about that.Exactly, foreach is a new, better language construct, but we didn't butcher for. I would love to see a nice solid proposal for 'match'.
Feb 17 2014
On 2/17/14, 7:42 AM, Daniel Murphy wrote:"Manu" <turkeyman gmail.com> wrote in message news:mailman.156.1392649746.6445.digitalmars-d puremagic.com...A "match" statement that figures type patterns and introduce names and all that - that might be more interesting (though being far from a game changer). But that's not quite what has been proposed in this thread. AndreiI agree, to an extent. That's why I say if it is to be improved, I guess it needs a new name. foreach eliminated almost all instances of for. I don't think anyone's upset about that.Exactly, foreach is a new, better language construct, but we didn't butcher for. I would love to see a nice solid proposal for 'match'.
Feb 17 2014
On 2/17/14, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:A "match" statement that figures type patterns and introduce names and all that - that might be more interesting (though being far from a game changer). But that's not quite what has been proposed in this thread.There are some interesting related Phobos pulls: Add functional style regex pattern-matching: https://github.com/D-Programming-Language/phobos/pull/1392 Add functional pattern matching for object references: https://github.com/D-Programming-Language/phobos/pull/1266 Add a functional switch function: https://github.com/D-Programming-Language/phobos/pull/1259
Feb 17 2014
"Andrei Alexandrescu" wrote in message news:ldtbcb$mel$1 digitalmars.com...A "match" statement that figures type patterns and introduce names and all that - that might be more interesting (though being far from a game changer).I doubt one can really know if it's a game changer until it has been implemented and experimented with. I'm not really in a position to design one for D, but I have had some positive experience with erlang's 'case' expressions. The real question is if we can make it clean and powerful enough to outdo a library solution.But that's not quite what has been proposed in this thread.Yeah, I was trying to derail this thread in a more useful direction.
Feb 17 2014
On 2/17/2014 10:54 AM, Andrei Alexandrescu wrote:On 2/17/14, 7:42 AM, Daniel Murphy wrote:Although I've said it before, I'd love to see Nemerle's match in D: https://github.com/rsdn/nemerle/wiki/Quick-guide#wiki-Pattern_Matching Especially together with its great algebraic types (Phobos's Algebraic still needs some beefing up, unfortunately).Exactly, foreach is a new, better language construct, but we didn't butcher for. I would love to see a nice solid proposal for 'match'.A "match" statement that figures type patterns and introduce names and all that - that might be more interesting (though being far from a game changer). But that's not quite what has been proposed in this thread.
Feb 17 2014
On Sunday, 16 February 2014 at 15:43:31 UTC, Manu wrote:int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; }I do agree that the breaks can get rather messy and I don't think that the current syntax is perfect. However I also find that in most situations where a switch statement is useful, it's not a bad idea to have it as a separate method anyways. In this case: int getDifficulty(int note) { switch(note) { case 60: .. case 71: return 0; case 72: .. case 83: return 1; case 84: .. case 95: return 2; case 96: .. case 107: return 3; default: return -1; } } Since it's using a return there's no break required and it's arguably a cleaner separation.
Feb 17 2014
On Sunday, 16 February 2014 at 15:43:31 UTC, Manu wrote:So D offers great improvements to switch(), but there are a few small things I wonder about. 1. case fall-through is not supported; explicit 'goto case n;' is required. With this in mind, 'break' is unnecessary. Why is it required? It could be implicit upon reaching the next case label, or a scope could be used (with support for omitting the scope for single statements as with if). It's really noisy, and annoying to write everywhere. 2. 'case 1, 3, 7, 8:' is awesome! ...but ranged cases have a totally different syntax: 'case 1: .. case 3:' Why settle on that syntax? The inconsistency looks kinda silly when they appear together in code. Surely it's possible to find a syntax that works without repeating case and ':'? It's also weird, because it seems that 'case n: .. case m:' is inclusive of m. This may be unexpected. I'm not sure it's reasonable to use the '..' syntax in this case for that reason. '..' is an [) range, case ranges must be [] so that it makes sense when dealing with enum key ranges. 3. Why is 'default' necessary? If I'm not switching on an enumerated type, then many values are meaningless. requiring an empty 'default: break;' line at the end is annoying and noisy. I often find myself tempted to rewrite blocks of successive if() logic comparing integers against values/ranges, but it looks silly since the scope rules are not explicit, and 'default: break;' always wastes an extra line. I like to reduce noise in my code, and these switch semantics threaten to simplify a lot of code, if not for these strange decisions (purely for legacy compliance?). Let's consider an example: Code like this: int difficulty = -1; if(e.note.note >= 60 && e.note.note < 72) difficulty = 0; else if(e.note.note >= 72 && e.note.note < 84) difficulty = 1; else if(e.note.note >= 84 && e.note.note < 96) difficulty = 2; else if(e.note.note >= 96 && e.note.note < 108) difficulty = 3; The repetition of e.note.note is annoying, and particular choice of comparisons are liable to result in out-by-ones. It's not nice code to read. Rewrites like this: int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; } That's horrid, it's much longer! And there are pointless wasted lines everywhere. The default case is a total waste, since -1 should just be assigned when initialising the variable above. We can compact it a bit like this: int difficulty; switch(e.note.note) { case 60: .. case 71: difficulty = 0; break; case 72: .. case 83: difficulty = 1; break; case 84: .. case 95: difficulty = 2; break; case 96: .. case 107: difficulty = 3; break; default: difficulty = -1; break; } But that's horrible too. It's not clear what vertical offset the 'break' statements shoudl appear at (I hate stacking up multiple statements across the same line!). The the default case is still a waste. Ideally: int difficulty = -1; switch(e.note.note) { case 60 .. 72: difficulty = 0; case 72 .. 84: difficulty = 1; case 84 .. 96: difficulty = 2; case 96 .. 108: difficulty = 3; } 'break's are unnecessary since fallthrough isn't allowed. Proper numeric range could be supported (assuming [) intervals). 'default' case is unnecessary, and removed. The switch and braces results in 3 extra lines, but I still feel this level of simplification results in code that is MUCH more readable than the sequence of if's I started with. It's super obvious what's going on. I have quite many blocks like this. A great man once (actually, frequently) said "If it doesn't look right, it probably isn't".Having also wrote a lot of switch statements in D I do mostly agree on these points. I think this example 'case 1: .. case 3:' is obvious. but I like 'case 1..3, 5, 6, 8, 9..10:' syntax better (Pascal) see how much typing I save. Break inside a switch should be rid of (Again Pascal) it's bloat. Having a default does get a bit annoying I see a lot of these.. That being said it's nice having that extra safety.
Feb 17 2014
On Sunday, 16 February 2014 at 15:43:31 UTC, Manu wrote:1. case fall-through is not supported;goto case; automagically goes to the next case.2. 'case 1, 3, 7, 8:' is awesome! ...but ranged cases have a totally different syntax: 'case 1: .. case 3:' Why settle on that syntax? The inconsistency looks kinda silly when they appear together in code.When implementing this on SDC. The .. syntax seems appropriate to me, the current one is clearly insane.3. Why is 'default' necessary? If I'm not switching on an enumerated type, then many values are meaningless. requiring an empty 'default: break;' line at the end is annoying and noisy.Sounds like an improvement over conventional switches to me.
Feb 18 2014