D - switch statement improvement?
- Ian Woollard (31/31) Sep 15 2003 Just had a quick look at the switch statement.
- Charles Sanders (12/43) Sep 15 2003 I like the idea of a nobreak statement ( this has been a popular topic) ...
- Ian Woollard (5/53) Sep 15 2003 Provided the nobreak statement is optional (just a nasty compiler warnin...
- Philippe Mori (29/36) Sep 15 2003 backward
- Matthew Wilson (8/46) Sep 15 2003 I think that both break and nobreak (I'd prefer "fallthrough") were
- Helmut Leitner (6/10) Sep 15 2003 Exactly. I would also vote to make "break or nobreak" mandatory.
- Matthew Wilson (1/6) Sep 15 2003 Yes, indeed. That was what I meant (and why I meant it :) ).
- John Boucher (3/12) Sep 15 2003 Hmmm, a compiler switch to say whether or not it is required... kinda st...
- Antti =?iso-8859-1?Q?Syk=E4ri?= (19/37) Sep 16 2003 I recall that there are good reasons for not having compile-time options
- Philippe Mori (9/27) Sep 16 2003 I agree with that solution where the compiler could find potential
- John Boucher (6/57) Sep 15 2003 I like the idea too (and I know C# does it), but I wonder if there are f...
- Charles Sanders (13/79) Sep 15 2003 Good point, I love the assignment's in conditionals too. That was one o...
- Philippe Mori (9/18) Sep 16 2003 Uses := for assignment instead of =...
- John Boucher (30/51) Sep 16 2003 Uh, I hope I didn't suggest having two different assignment operators to...
- Philippe Mori (60/107) Sep 16 2003 It is the same operator... just that the short version is more restricte...
- John Boucher (6/122) Sep 16 2003 Wow, good ideas. And I misspoke with the !=, I knew something was wrong....
- Riccardo De Agostini (32/36) Sep 16 2003 to
- Hauke Duden (37/61) Sep 16 2003 I'd like to see a nobreak statement, but I absolutely hate to see a
- Antti =?iso-8859-1?Q?Syk=E4ri?= (35/41) Sep 16 2003 Of course, you *could* make the switch statement a generalization of the
- Hauke Duden (19/26) Sep 16 2003 I don't know. To me this seems to be a feature that complicates the the
- Antti =?iso-8859-1?Q?Syk=E4ri?= (98/122) Sep 16 2003 The compiler might be slightly more complicated, or then again it could
- Philippe Mori (66/88) Sep 16 2003 Here I suppose you would like that every items be compared in turn for
-
Hauke Duden
(36/49)
Sep 17 2003
- Antti =?iso-8859-1?Q?Syk=E4ri?= (131/165) Sep 17 2003 I try not to post only my opinions but also the thinking process behind
- John Boucher (39/46) Sep 17 2003 Here you seem to refer only to falling-through from an empty case, which...
- Hauke Duden (73/100) Sep 18 2003 You seem to alternate between wanting to have an uber-powerful switch
- Erik Baklund (7/27) Sep 18 2003 Way to go!
- Philippe Mori (22/41) Sep 18 2003 I also like that syntax... Clear, no problem with it (fall-through) and
- Sean L. Palmer (6/11) Sep 19 2003 I like that branch too.
- Philippe Mori (33/46) Sep 18 2003 I agree with that extension....
- Hauke Duden (35/35) Sep 17 2003 I just thought of another thing:
- Antti =?iso-8859-1?Q?Syk=E4ri?= (29/76) Sep 17 2003 The example below is hypothetical, I believe.
- Hauke Duden (6/13) Sep 18 2003 Actually, my main point was to keep it consistent with the rest of the
- Riccardo De Agostini (5/10) Sep 16 2003 Great! Now I'm curious about Walter's opinion, he's the compiler guy aft...
- John Boucher (28/28) Sep 16 2003 Oh, so we're going to start specifying a new syntax for the switch state...
- Riccardo De Agostini (9/33) Sep 18 2003 statements
- Riccardo De Agostini (16/28) Sep 16 2003 Nice and right objection. I blind-copied it from VB. "is" might as well ...
- Erik Baklund (4/40) Sep 16 2003 Please not that the suggested syntax leaves both 'break' and 'nobreak'
- Riccardo De Agostini (4/6) Sep 16 2003 Of course: break should be implied. Thanks for pointing that out.
- Erik Baklund (29/35) Sep 16 2003 I am sorry that my statement came out a bit garbeled.
- Philippe Mori (27/55) Sep 16 2003 null-code
- John Boucher (6/65) Sep 16 2003 Oh, yeah, specific jumping rather than falling-through _is_ better. Let'...
- Erik Baklund (25/84) Sep 17 2003 Nonono .. no goto!
- John Boucher (40/48) Sep 17 2003 I think I agree. I definitely agree with your first assertion, that ther...
- Philippe Mori (19/49) Sep 18 2003 Buuut...
- Riccardo De Agostini (4/5) Sep 16 2003 Except for the compiler option, I meant. Let D be D.
- Philippe Mori (30/46) Sep 16 2003 For me, multiple values is OK and range also (with either syntax)
- Walter (4/8) Nov 26 2003 A good idea, but this is already addressed in D where the default case, ...
- Hauke Duden (8/16) Nov 26 2003 Not that I'm against that, but it seems a little inconsistent. What
- Charles Sanders (5/23) Nov 26 2003 Seconded!
- Matthew Wilson (12/18) Nov 26 2003 Wow! That's a *really*, *REALLY* bad idea.
- Ant (6/14) Nov 26 2003 I agree!
- Charles Sanders (5/21) Nov 26 2003 I havent come accross it, but mark this up as another complaint ! :).
- Vathix (13/29) Nov 26 2003 if
- Hauke Duden (6/8) Nov 26 2003 Huh? How can that happen? Doesn't the compiler check at compile time
- Juan C. (13/13) Nov 26 2003 As regards the switch statement, I continue to like the way C# does it; ...
- Walter (16/23) Nov 26 2003 exception
- Hauke Duden (12/33) Nov 27 2003 VC6 issues a warning in that case:
- Mark T (2/20) Nov 27 2003 why allow it? this is bad code, at least issue a warning because someone...
- Hauke Duden (15/38) Nov 27 2003 Well, if 0 is an invalid argument, then throwing an exception would be
- Matthew Wilson (4/26) Nov 27 2003 someday
- Felix (9/36) Nov 28 2003 Me too... I think that syntax should be more strict in D than in C/C++, ...
- Walter (3/4) Nov 27 2003 I need to write a short paper on why I philosophically object to warning...
- Hauke Duden (11/18) Nov 27 2003 I know the way you feel about this. Maybe you're right and the necessity...
- Walter (4/7) Nov 27 2003 You're right that it would be better to do it at compile time, but like
- Roberto Mariottini (4/8) Nov 28 2003 You forget you philosophically object to compiler options, too.
- Walter (4/12) Nov 28 2003 warnings!
- Sean L. Palmer (35/52) Nov 28 2003 case:
- Walter (22/31) Nov 28 2003 I think that protecting against CPU hardware failures is beyond the scop...
- Matthew Wilson (18/49) Nov 28 2003 of
- Ilya Minkov (12/14) Nov 29 2003 D-ctatorship rules. :>
- Walter (5/9) Nov 29 2003 You're right that one advantage to having assertions as part of the synt...
- Ilya Minkov (24/30) Nov 30 2003 I definately didn't mention the optimizer. What i meant is that
-
Walter
(10/38)
Nov 30 2003
Well, that's just what an optimizer is: a code flow analyzer.
- Matthew Wilson (26/29) Nov 30 2003 I can honestly say that neither issue has hurt me once in, say, the last
- Sean L. Palmer (20/49) Dec 01 2003 I think your numbers are spot on.
- Ilya Minkov (23/29) Dec 02 2003 I was advocating something different: it makes sense to do this as part ...
- Walter (46/73) Dec 05 2003 "i'm not
- one_mad_alien hotmail.com (22/29) Dec 06 2003 and then someone else comes along and changes the code to
- Walter (8/13) Dec 08 2003 anyway)
- Georg Wrede (24/25) Dec 06 2003 (an excellent discussion deleted)
- Georg Wrede (36/36) Nov 30 2003 I've had a hard time reading this thread. Instead of a discussion,
- Matthew Wilson (4/40) Nov 30 2003 Sorry to be obtuse, but I don't glean what your position is? C/C++ statu...
- Georg Wrede (38/40) Dec 01 2003 (I was aspiring to transcend the current issues themselves, but what
- Sean L. Palmer (8/11) Dec 01 2003 The default, implicit, behavior should be the most common behavior neede...
- Felix (9/20) Dec 01 2003 Yeah, I agree. I'd like to use smthng like:
- Antti =?iso-8859-1?Q?Syk=E4ri?= (46/56) Dec 01 2003 This reminds of the classic way Java novices learn to use exception
- Sean L. Palmer (12/49) Dec 01 2003 Terse code is much easier to scan visually (think scanning a 1000-line
- Berin Loritsch (43/61) Dec 01 2003 There are a couple things I really don't like about that code anyway. F...
- Walter (32/63) Dec 09 2003 to be
- Russ Lewis (9/9) Nov 30 2003 Walter, I just wanted to weigh in here. Your current design (implicit
-
Walter
(5/10)
Dec 06 2003
At least somebody likes it
. - Alix Pexton (21/38) Dec 07 2003 I've been pondering this for a while, and I know that my view is going o...
- Sean L. Palmer (34/50) Dec 07 2003 I thinkWalter's way is better than not checking at all, but a few people...
- Matthew Wilson (12/68) Dec 07 2003 That's the most cogent opinion yet expressed. I heartily "hear, hear" it...
- Hauke Duden (36/80) Dec 08 2003 I agree. Also, I would like to add one additonal point:
- Lars Ivar Igesund (21/101) Dec 08 2003 Good point. Especially since it is possible to switch on strings, but as
- Ant (3/7) Dec 08 2003 ah! ah! let's see Walter dodging this one ;)
- J Anderson (21/34) Dec 08 2003 Here's one reason.
- Hauke Duden (5/33) Dec 08 2003 You are trying to use one flaw to justify another!
- J Anderson (40/74) Dec 08 2003 For:
- Hauke Duden (14/40) Dec 08 2003 What I said was that D should have both a IMplicit break and an EXplicit...
- Juan C. (14/54) Dec 08 2003 Oh, well then you'll love this:
- Walter (46/80) Dec 08 2003 on
- Patrick Down (33/56) Dec 09 2003 Yes I would view the switch statement the same way.
- Hauke Duden (17/42) Dec 09 2003 There is one important difference: it works differently in all other
- J Anderson (6/43) Dec 09 2003 Do you send out distributions that are compiled in debug mode? In
- Hauke Duden (6/8) Dec 10 2003 Problem is, D doesn't do an assert, it throws an exception
- Patrick Down (4/12) Dec 10 2003 Actaully these execptions are compliled out in the release version,
- Juan C. (15/27) Dec 10 2003 I still don't think that the compiler should spend its time checking for...
- Ilya Minkov (27/35) Dec 10 2003 We're very far from experiencing any speed problems at compilation.
- J Anderson (2/21) Dec 10 2003 That is what I ment.
- Lars Ivar Igesund (5/13) Nov 26 2003 if
- Walter (10/22) Nov 27 2003 if
- Matthew Wilson (21/41) Nov 27 2003 be
- Charles Sanders (14/57) Nov 27 2003 Have to agree here, I rareley ( never ? ) use exceptions , and dont like
- Matthew Wilson (5/7) Nov 27 2003 Exactamundo, my friend.
- Walter (69/76) Nov 27 2003 errors,
- Matthew Wilson (19/98) Nov 27 2003 like
- Roberto Mariottini (9/22) Nov 28 2003 I also support requiring default. The laziness is your biggest enemy,
- Walter (5/8) Nov 28 2003 are
- Matthew Wilson (5/11) Nov 28 2003 values
- Matthew Wilson (7/22) Nov 28 2003 sensible
- Walter (9/16) Nov 28 2003 almost
- Matthew Wilson (14/33) Nov 28 2003 ...
- Walter (11/29) Dec 02 2003 It's not achievable at compile time, regardless of whether the default i...
- Matthew Wilson (5/13) Dec 02 2003 a
- Walter (10/25) Dec 08 2003 make
-
Julio César Carrascal Urquijo
(13/18)
Dec 09 2003
"Walter"
wrote in message -
Walter
(3/4)
Dec 18 2003
I could argue it both ways
. - Julio César Carrascal Urquijo (3/7) Dec 18 2003 At least in debug builds, please! (Just like array bounds checking)
- Walter (3/12) Dec 19 2003 It's a good idea, but I have to redo the template stuff first.
- Sean L. Palmer (5/6) Dec 19 2003 Shall we reopen the discussion, or do you already know what you are goin...
- Walter (4/10) Dec 19 2003 I think I know what to do.
-
Julio César Carrascal Urquijo
(4/5)
Dec 19 2003
Walter
escribió en el mensaje de noticias - Ilya Minkov (5/11) Nov 29 2003 Requiring default will bring us to people typing "default: break;"
- Berin Loritsch (3/13) Dec 01 2003 For some people, that is exactly what they want. You do need to walk a ...
- Walter (20/22) Dec 02 2003 A similar problem has happened with Java where it required you to list t...
- Hauke Duden (10/16) Dec 02 2003 You'd prefer runtime type checking to compile time type checking?
- Walter (15/31) Dec 02 2003 then?
- Matthew Wilson (14/45) Dec 02 2003 runtime
- Walter (12/21) Dec 08 2003 arguments
- Hauke Duden (34/64) Dec 09 2003 I hate to make this more complicated, but ... I very much prefer the
- Walter (9/37) Dec 09 2003 Yes, it's a clear difference in our styles of using switch statements. M...
- Matthew Wilson (6/40) Dec 09 2003 in
- Lewis Miller (16/16) Dec 09 2003 This probably wont help any but a switch that acts like visual basics Se...
- J C Calvarese (5/29) Dec 09 2003 This is my preferred style as well. (Maybe it's from all of my
- Lewis (7/44) Dec 09 2003 interestingly enough, vb also has a switch statement
- Dan Liebgold (34/50) Dec 09 2003 I must agree with this approach. This, to my mind, is the right way (TM...
- Felix (6/66) Dec 09 2003 Me too, I do not like that "break"'s in the switch.
- J Anderson (3/20) Dec 09 2003 This is my preference as well. I guess the D version would look
- Georg Wrede (13/22) Dec 10 2003 These statements combined would seem to vote for an
- The Lone Haranguer (6/27) Dec 09 2003 C has an implicit default:break; ?
- Walter (6/11) Dec 09 2003 Yes.
- Russ Lewis (21/69) Dec 10 2003 I think that you are missing one of the central tenets of Walter's
- Walter (4/5) Dec 10 2003 Thanks! At the end of the day, I just have to make a decision and stick ...
- The Lone Haranguer (4/24) Dec 10 2003 Well, based on both those arguments, fall-through should be abandoned. I
- The Lone Haranguer (28/48) Dec 10 2003 I think perhaps this could be used as an argument for strongly-typed boo...
- Andy Friesen (3/5) Dec 02 2003 Nondeterministic bugs are great for burning a few hours (and brain cells...
- Walter (4/8) Dec 08 2003 Yup. That's why DbC is so valuable, as the earlier in the program the bu...
- Lars Ivar Igesund (16/18) Dec 03 2003 I might accept your solution if you make a minor change. Don't use
- Brad Beveridge (18/44) lid Date I may be not getting this argument.
- Matthew Wilson (15/28) Dec 03 2003 That is not so. We're saying that the default must be specified.
- Georg Wrede (32/32) Dec 03 2003 I've gone through reams of C code, and I am not convinced anymore
- Carlos Santander B. (16/16) Dec 03 2003 [warning: some of you might not find this idea appealing.]
- J C Calvarese (38/55) Dec 03 2003 I think you might be on to something here. I think "select" would be a
- Walter (20/31) Dec 08 2003 I actually agree with you. D doesn't compel you to use good practices.
- The Lone Harnguer (9/13) Dec 09 2003 Uh uh uh...
- J Anderson (7/16) Dec 09 2003 If C code porting was 100% supported by D, then we'd be back to C++. D
- Hauke Duden (35/46) Dec 03 2003 I suggested something like that a while ago. I'll just paste part of
- Vathix (1/21) Dec 03 2003 I like it. I think branch is a good name as well.
- Felix (3/28) Dec 04 2003 Me too, I like it. Maybe D should implement both versions: switch and br...
- Dan Liebgold (25/25) Dec 05 2003 Someone has probably already mentioned this, but C#
- Richard Krehbiel (12/40) Dec 05 2003 Well, there's nothing that a goto can't "solve." :-) In fact, it's
- Georg Wrede (50/50) Dec 05 2003 The following is cut from D lexer.c:
- Georg Wrede (12/12) Dec 05 2003 The D if-statement demands a {} instead of a semicolon.
- Matthew Wilson (3/15) Dec 05 2003 I like the cut of your jib
- Georg Wrede (18/18) Dec 05 2003 The following should protect (at least newbies), and my
- Natsayer (2/20) Dec 05 2003
- Georg Wrede (23/25) Dec 06 2003 Yeah. That was the whole point.
- Matthew Wilson (1/17) Dec 03 2003 Exactly. What could be simpler?
- Antti =?iso-8859-1?Q?Syk=E4ri?= (93/102) Dec 03 2003 There's been a lot of debate on the matter and a lot of different strong
- Berin Loritsch (20/20) Dec 03 2003 In Java we are used to the language runtime issuing exceptions for
- Walter (17/27) Dec 08 2003 I agree. This is what D already does:
- Walter (15/28) Dec 08 2003 I apologize for speaking metaphorically, what actually happens is not an
- Felix (3/33) Dec 09 2003 I agree, esp. with the last point. Things are a lot clearer for me now. ...
- Berin Loritsch (31/38) Dec 09 2003 Yes and no. Being a Java guru, most of the issues resolve around people...
- Walter (34/54) Dec 09 2003 new
- Matthew Wilson (10/37) Dec 09 2003 This is simply wrong. I hear about this from time to time, and it is
- Berin Loritsch (68/95) Dec 09 2003 Maybe it was and they just didn't want to admit it. ;P
- Hauke Duden (27/36) Dec 09 2003 That won't suffice. The main problem I have with JAVA's forced throws
- Walter (6/6) Dec 09 2003 Here's an article on the topic:
- Russ Lewis (11/102) Dec 09 2003 Remind me, Walter. Why don't we have (optional) throws statements?
- Ilya Minkov (36/40) Dec 09 2003 You don't need the experts to tell you that. I just took 2 randomly
- Ant (4/12) Dec 02 2003 You are contradicting your self because you are forcing programers
- Walter (4/6) Dec 02 2003 But D doesn't force them to explicitly write it! Sorry if I wasn't clear
- Ant (9/15) Dec 02 2003 You can't convince me on this one ;)
-
Walter
(3/4)
Dec 02 2003
I'll wait for when it finds an overlooked bug in your code
. - Matthew Wilson (8/14) Dec 02 2003 So what? It does force them to have it.
- Walter (9/23) Dec 08 2003 of
- J C Calvarese (24/62) Dec 09 2003 Walter,
- Sean L. Palmer (13/35) Dec 03 2003 I think that you should not just code "any which way you want to" becaus...
- Berin Loritsch (14/111) Dec 01 2003 Following is Walters reasoning why the default checking can't be done at
- Berin Loritsch (4/16) Dec 01 2003 Sounds like it is calling for a compiler check to me. I don't mind if t...
- Vathix (9/9) Sep 16 2003 How about a different word for case, like bcase, casex, fcase or ...
- Richard Krehbiel (15/15) Sep 17 2003 My Humble Opinion re: switch:
- J Anderson (99/99) Sep 17 2003
- Matthew Wilson (71/102) Nov 28 2003 Does anyone disagree that C/C++'s switch semantics are dangerous, even i...
- Lars Ivar Igesund (4/6) Nov 29 2003 I like!
- Berin Loritsch (14/39) Dec 01 2003 I think the principle of the easiest thing would mean that we have the c...
- Matthew Wilson (18/57) Dec 01 2003 Hear, hear!
- Ant (4/7) Dec 01 2003 Maybe the compiler could add that instead of throwing a fatal error.
Just had a quick look at the switch statement. I noticed the syntax is: switch (foobar) { case 0: dostuff(); // I've forgotten to break; all is lost. case 1: domorestuffIdidntreallywantto(); break; default: } This isn't such a good idea. The default behaviour is really unsafe. I would suggest a 'nobreak' statement for cases where you really do want the code to fall through; otherwise the compiler probably should fail to compile (possibly switcheable off with a compiler option.) e.g. switch (foobar) { case 0: dostuff(); nobreak; // we fall through, but that's fine. case 1: case 2: // note no nobreak required (although I wouldn't cry if it was) domorestuff(); break; default: } Anyway, just an idea; probably a very good one IMNHO though. You might also consider the same idea in empty if and for statements. -Ian
Sep 15 2003
I like the idea of a nobreak statement ( this has been a popular topic) , I think the reason for keeping this is backward compatibility ( on a user level ). I always hated this behavior, and could never understand why this was the default. Can we change it ? Taking a vote might be helpful to Walter. I vote we fix this beast once and for all! Charles "Ian Woollard" <Ian_member pathlink.com> wrote in message news:bk5nri$14cm$1 digitaldaemon.com...Just had a quick look at the switch statement. I noticed the syntax is: switch (foobar) { case 0: dostuff(); // I've forgotten to break; all is lost. case 1: domorestuffIdidntreallywantto(); break; default: } This isn't such a good idea. The default behaviour is really unsafe. Iwouldsuggest a 'nobreak' statement for cases where you really do want the codetofall through; otherwise the compiler probably should fail to compile(possiblyswitcheable off with a compiler option.) e.g. switch (foobar) { case 0: dostuff(); nobreak; // we fall through, but that's fine. case 1: case 2: // note no nobreak required (although I wouldn't cry if it was) domorestuff(); break; default: } Anyway, just an idea; probably a very good one IMNHO though. You might also consider the same idea in empty if and for statements. -Ian
Sep 15 2003
In article <bk5o47$15o3$1 digitaldaemon.com>, Charles Sanders says...I like the idea of a nobreak statement ( this has been a popular topic) , I think the reason for keeping this is backward compatibility ( on a user level ).Provided the nobreak statement is optional (just a nasty compiler warning if left out), or mandatory but the compiler has a flag to make it ignore it's omission (but still warn- my colleagues ARE out to get me :-) ), then backward compatibility is, in practice, a non issue.Charles "Ian Woollard" <Ian_member pathlink.com> wrote in message news:bk5nri$14cm$1 digitaldaemon.com...Just had a quick look at the switch statement. I noticed the syntax is: switch (foobar) { case 0: dostuff(); // I've forgotten to break; all is lost. case 1: domorestuffIdidntreallywantto(); break; default: } This isn't such a good idea. The default behaviour is really unsafe. Iwouldsuggest a 'nobreak' statement for cases where you really do want the codetofall through; otherwise the compiler probably should fail to compile(possiblyswitcheable off with a compiler option.) e.g. switch (foobar) { case 0: dostuff(); nobreak; // we fall through, but that's fine. case 1: case 2: // note no nobreak required (although I wouldn't cry if it was) domorestuff(); break; default: } Anyway, just an idea; probably a very good one IMNHO though. You might also consider the same idea in empty if and for statements. -Ian
Sep 15 2003
II like the idea of a nobreak statement ( this has been a popular topic) ,ifthink the reason for keeping this is backward compatibility ( on a user level ).Provided the nobreak statement is optional (just a nasty compiler warningleft out), or mandatory but the compiler has a flag to make it ignore it's omission (but still warn- my colleagues ARE out to get me :-) ), thenbackwardcompatibility is, in practice, a non issue.I think that nobreak is a good keyword and should be required if no it would otherwise fall-through. That is, we ne it if there are no break, return, throw, continue or goto statement (or similar). I think that compatibility is not a good reason in this case to make it facultative. In my opinion even a good programmer might forget one or two break in a year and spend a few minutes to find a bug that could be easily prevented by the compiler by requiring explicit exit... IMO, the time saved in debugging for common programmers worth well the few added keystroke... and if break is optional, we would be safer than C++ with less code to write in typical application (since more than 90% of case needs a break). For compatibility with C++, with should allows to still uses break (easy conversion from C++ to D) and define nobreak as an empty statement in C++ (for easier conversion in the other direction). #define nobreak (void)0 /* in C++ */ That way, by using both break and nobreak the code is portable between C++ and D. Also, I would suggest to make these kind of change soon before a lot of code depend on it... I wote that fall-through must be explicitly asked (nobreak or something else)... For weither break is required or optional, I would prefer optional but I can live with if required... And I like nobreak as it is explicit, short and documentative... but labelled jump is acceptable... and a bit safer if the order is modified!
Sep 15 2003
I think that both break and nobreak (I'd prefer "fallthrough") were required. That's the safest (albeit the most verbose) way to go "Philippe Mori" <philippe_mori hotmail.com> wrote in message news:bk5uqe$1tnn$1 digitaldaemon.com...,I like the idea of a nobreak statement ( this has been a popular topic)Iwarningthink the reason for keeping this is backward compatibility ( on a user level ).Provided the nobreak statement is optional (just a nasty compilerifit'sleft out), or mandatory but the compiler has a flag to make it ignorewouldomission (but still warn- my colleagues ARE out to get me :-) ), thenbackwardcompatibility is, in practice, a non issue.I think that nobreak is a good keyword and should be required if no itotherwise fall-through. That is, we ne it if there are no break, return, throw, continue or goto statement (or similar). I think that compatibility is not a good reason in this case to make it facultative. In my opinion even a good programmer might forget one or two break in a year and spend a few minutes to find a bug that could be easily prevented by the compiler by requiring explicit exit... IMO, the time saved in debugging for common programmers worth well the few added keystroke... and if break is optional, we would be safer than C++ with less code to write in typical application (since more than 90% of case needs a break). For compatibility with C++, with should allows to still uses break (easy conversion from C++ to D) and define nobreak as an empty statement in C++ (for easier conversion in the other direction). #define nobreak (void)0 /* in C++ */ That way, by using both break and nobreak the code is portable between C++ and D. Also, I would suggest to make these kind of change soon before a lot of code depend on it... I wote that fall-through must be explicitly asked (nobreak or something else)... For weither break is required or optional, I would prefer optional but I can live with if required... And I like nobreak as it is explicit, short and documentative... but labelled jump is acceptable... and a bit safer if the order is modified!
Sep 15 2003
Matthew Wilson wrote:I think that both break and nobreak (I'd prefer "fallthrough") were required. That's the safest (albeit the most verbose) way to goExactly. I would also vote to make "break or nobreak" mandatory. So you can convert code from all C family languages without any risk. -- Helmut Leitner leitner hls.via.at Graz, Austria www.hls-software.com
Sep 15 2003
Yes, indeed. That was what I meant (and why I meant it :) ).I think that both break and nobreak (I'd prefer "fallthrough") were required. That's the safest (albeit the most verbose) way to goExactly. I would also vote to make "break or nobreak" mandatory. So you can convert code from all C family languages without any risk.
Sep 15 2003
Hmmm, a compiler switch to say whether or not it is required... kinda starting to border on being a pragma, isn't it? In article <bk5pk9$1a54$1 digitaldaemon.com>, Ian Woollard says...In article <bk5o47$15o3$1 digitaldaemon.com>, Charles Sanders says...I like the idea of a nobreak statement ( this has been a popular topic) , I think the reason for keeping this is backward compatibility ( on a user level ).Provided the nobreak statement is optional (just a nasty compiler warning if left out), or mandatory but the compiler has a flag to make it ignore it's omission (but still warn- my colleagues ARE out to get me :-) ), then backward compatibility is, in practice, a non issue.Charles
Sep 15 2003
I recall that there are good reasons for not having compile-time options that change the semantics of the code. If my memory is not failing me, Walter said somewhere that he has a rather strong opinion about this. Generally I think the same, but I'd allow the following border case: - Default behavior of switch statement is to break. - Keyword "fallthrough" is required to, well, fall through. - A compiler-switch "-require-explicit-break-or-fallthrough" that will require explicit "break;" or "fallthrough;". The purpose of this switch is to make porting C apps easier. That way you could write native D apps without writing the tedious break statement. After all, as Philippe said, the behavior in 9 out of 10 cases is to break. The superfluous breaks just clutter up the code. If you'd need to port C apps, just use the option -require-explicit-break-or-fallthrough and insert "fallthrough" where there is no break. After the code compiles, you can remove the option and works correctly. There will be a couple of redundant break statements but they won't hurt anyone. -Antti In article <bk615t$22md$1 digitaldaemon.com>, John Boucher wrote:Hmmm, a compiler switch to say whether or not it is required... kinda starting to border on being a pragma, isn't it? In article <bk5pk9$1a54$1 digitaldaemon.com>, Ian Woollard says...In article <bk5o47$15o3$1 digitaldaemon.com>, Charles Sanders says...I like the idea of a nobreak statement ( this has been a popular topic) , I think the reason for keeping this is backward compatibility ( on a user level ).Provided the nobreak statement is optional (just a nasty compiler warning if left out), or mandatory but the compiler has a flag to make it ignore it's omission (but still warn- my colleagues ARE out to get me :-) ), then backward compatibility is, in practice, a non issue.Charles
Sep 16 2003
I recall that there are good reasons for not having compile-time options that change the semantics of the code. If my memory is not failing me, Walter said somewhere that he has a rather strong opinion about this. Generally I think the same, but I'd allow the following border case: - Default behavior of switch statement is to break. - Keyword "fallthrough" is required to, well, fall through. - A compiler-switch "-require-explicit-break-or-fallthrough" that will require explicit "break;" or "fallthrough;". The purpose of this switch is to make porting C apps easier. That way you could write native D apps without writing the tedious break statement. After all, as Philippe said, the behavior in 9 out of 10 cases is to break. The superfluous breaks just clutter up the code. If you'd need to port C apps, just use the option -require-explicit-break-or-fallthrough and insert "fallthrough" where there is no break. After the code compiles, you can remove the option and works correctly. There will be a couple of redundant break statements but they won't hurt anyone. -AnttiI agree with that solution where the compiler could find potential errors when porting code or for people that have learn that other language want to avoid common pitfall (here would think it fall through). OTOH I think that requiring both break and nobreak (or fallthrough) would be better since it remove the need of an extra compiler option that some will want to uses anyway (like those that compile at level 4 under Visual C++ even if it give far too much warning for correct code...)
Sep 16 2003
errors caused by this than by if ( x = y ) which Walter has done away with, although I don't entirely agree with the way he did. In article <bk5o47$15o3$1 digitaldaemon.com>, Charles Sanders says...I like the idea of a nobreak statement ( this has been a popular topic) , I think the reason for keeping this is backward compatibility ( on a user level ). I always hated this behavior, and could never understand why this was the default. Can we change it ? Taking a vote might be helpful to Walter. I vote we fix this beast once and for all! Charles "Ian Woollard" <Ian_member pathlink.com> wrote in message news:bk5nri$14cm$1 digitaldaemon.com...John Boucher -- Quite contrary The King had Humpty pushed.Just had a quick look at the switch statement. I noticed the syntax is: switch (foobar) { case 0: dostuff(); // I've forgotten to break; all is lost. case 1: domorestuffIdidntreallywantto(); break; default: } This isn't such a good idea. The default behaviour is really unsafe. Iwouldsuggest a 'nobreak' statement for cases where you really do want the codetofall through; otherwise the compiler probably should fail to compile(possiblyswitcheable off with a compiler option.) e.g. switch (foobar) { case 0: dostuff(); nobreak; // we fall through, but that's fine. case 1: case 2: // note no nobreak required (although I wouldn't cry if it was) domorestuff(); break; default: } Anyway, just an idea; probably a very good one IMNHO though. You might also consider the same idea in empty if and for statements. -Ian
Sep 15 2003
fewererrors caused by this than by if ( x = y ) which Walter has done awaywith,although I don't entirely agree with the way he did.Good point, I love the assignment's in conditionals too. That was one of the problems I had with python. Walter what can we do ( if anything ) to convince you to allow this and the nobreak ? Charles "John Boucher" <John_member pathlink.com> wrote in message news:bk5pkl$1a5p$1 digitaldaemon.com...fewererrors caused by this than by if ( x = y ) which Walter has done awaywith,although I don't entirely agree with the way he did. In article <bk5o47$15o3$1 digitaldaemon.com>, Charles Sanders says...II like the idea of a nobreak statement ( this has been a popular topic) ,Ithink the reason for keeping this is backward compatibility ( on a user level ). I always hated this behavior, and could never understand why this was the default. Can we change it ? Taking a vote might be helpful to Walter.codevote we fix this beast once and for all! Charles "Ian Woollard" <Ian_member pathlink.com> wrote in message news:bk5nri$14cm$1 digitaldaemon.com...Just had a quick look at the switch statement. I noticed the syntax is: switch (foobar) { case 0: dostuff(); // I've forgotten to break; all is lost. case 1: domorestuffIdidntreallywantto(); break; default: } This isn't such a good idea. The default behaviour is really unsafe. Iwouldsuggest a 'nobreak' statement for cases where you really do want thetoJohn Boucher -- Quite contrary The King had Humpty pushed.fall through; otherwise the compiler probably should fail to compile(possiblyswitcheable off with a compiler option.) e.g. switch (foobar) { case 0: dostuff(); nobreak; // we fall through, but that's fine. case 1: case 2: // note no nobreak required (although I wouldn't cry if it was) domorestuff(); break; default: } Anyway, just an idea; probably a very good one IMNHO though. You might also consider the same idea in empty if and for statements. -Ian
Sep 15 2003
Uses := for assignment instead of =... := would always be required in conditional... and IMO should always be required but we could allows = where it is safe to assumes that the user want to do an assignment. int a = b; // OK to uses = here a = b; // could be OK here since the result is not used. (a = b).callAMember(); // would be ok if member is not also a // member of bool. if (a := b) { } // Here := is required (or extra ())fewererrors caused by this than by if ( x = y ) which Walter has done awaywith,although I don't entirely agree with the way he did.Good point, I love the assignment's in conditionals too. That was one of the problems I had with python. Walter what can we do ( if anything ) to convince you to allow this and the nobreak ? Charles
Sep 16 2003
In article <bk7ev1$alu$1 digitaldaemon.com>, Philippe Mori says...Uh, I hope I didn't suggest having two different assignment operators to do the same thing, with one being used in tests and the other one not. That's just wrong. I _did_ suggest replacing the bare equal sign (=) assignment operator with a colon-equal (:=) a la Pascal, and I stand by that. To anger several of you further allow me to go several steps farther over the edge and suggest redoing all the assignment operators to include a colon... = becomes := += becomes :+ -= becomes :- *= becomes :* /= becomes :/ %= becomes :% <<= becomes :<<Uses := for assignment instead of =... := would always be required in conditional... and IMO should always be required but we could allows = where it is safe to assumes that the user want to do an assignment. int a = b; // OK to uses = here a = b; // could be OK here since the result is not used. (a = b).callAMember(); // would be ok if member is not also a // member of bool. if (a := b) { } // Here := is required (or extra ())fewererrors caused by this than by if ( x = y ) which Walter has done awaywith,although I don't entirely agree with the way he did.Good point, I love the assignment's in conditionals too. That was one of the problems I had with python. Walter what can we do ( if anything ) to convince you to allow this and the nobreak ? Charles!= becomes :! &= becomes :& |= becomes :| ^= becomes :^ ~= becomes :~ Did I forget any? If not for D, then for the language that is sure to come after D. Oh, oh, oh -- I just had an even whackier idea... Howsabout we require something to tell the compiler that we really do want to do the assignment in the test? Like: [safe] if ( x = y ) ... ; John Boucher The King had Humpty pushed.= becomes :>>
Sep 16 2003
do theUses := for assignment instead of =... := would always be required in conditional... and IMO should always be required but we could allows = where it is safe to assumes that the user want to do an assignment. int a = b; // OK to uses = here a = b; // could be OK here since the result is not used. (a = b).callAMember(); // would be ok if member is not also a // member of bool. if (a := b) { } // Here := is required (or extra ())Uh, I hope I didn't suggest having two different assignment operators tosame thing, with one being used in tests and the other one not. That'sjustwrong.It is the same operator... just that the short version is more restricted... but if := is always used, it is OK for me... But still allowing = would allows easier porting of existing code as := would be seldom required...I _did_ suggest replacing the bare equal sign (=) assignment operator withacolon-equal (:=) a la Pascal, and I stand by that. To anger several of you further allow me to go several steps farther over the edge and suggestredoingall the assignment operators to include a colon... = becomes := += becomes :+ -= becomes :- *= becomes :* /= becomes :/ %= becomes :% <<= becomes :<<!= becomes :! &= becomes :& |= becomes :| ^= becomes :^ ~= becomes :~ Did I forget any?= becomes :>>If not for D, then for the language that is sure to come after D.I think that != should not be here. Does != means not equal (i.e. <>). This is a comparison and not an assignment!!! I think those changes are essentially useless and will make porting code a lot harder... And they are less visible (= is easier to spot than : in code)Oh, oh, oh -- I just had an even whackier idea... Howsabout we require something to tell the compiler that we really do wantto dothe assignment in the test? Like: [safe] if ( x = y ) ... ;If we have such a think, then we would like to be able to uses it in other context where like: - comparison or assignment between signed/unsigned - possible truncation - no break in a switch case (hey I'm back on switch discussion!) - any other warnings What I dislike with your solution is that it is not possible to apply the attribute only to a part on an expression... so in complex situations we might uses safe for one thing and hide another problem... $,?,...) that would modify the warnings that the compiler would normally give: We could have for example as prefix: : This is an assignment operator prefix ? This is a conditionnal operator prefix implicit conversion) This is a free (unsafe) operator prefix (allows more conversions like double to int, most anything to bool, base to derived...) $ Handle null object Some examples: if (a $== b) { } // Ok even if a, b or both are null if (a ?= b) { } // Is a equal to b if (a := b) { } assignment and test int i; double d; unsigned u; i = d; // Ok, allows truncation and other less safe conversion if (i == u) { } // No warning for comparing signed/unsigned -u; // No warning for negating an unsigned. base[] ba; derived[] de; Note that some case like just above are not very usefull for regular code but might be interesting in template code where we might be more or less restrictive in some cases. to indicate if we we want to be safer than usual (almost no conversion allowed) or allows more automatic conversions to happen automatically (for example converting a double to an int as in: void f( int i) { ... } f(25.5);John Boucher The King had Humpty pushed.
Sep 16 2003
In article <bk84fu$2kbi$1 digitaldaemon.com>, Philippe Mori says...Wow, good ideas. And I misspoke with the !=, I knew something was wrong. I don't mean to change the not-equal-to operator, I mean to add an "assign the not of" operator, my bad. John Boucher -- Self-contrary The King had Humpty pusheddo theUses := for assignment instead of =... := would always be required in conditional... and IMO should always be required but we could allows = where it is safe to assumes that the user want to do an assignment. int a = b; // OK to uses = here a = b; // could be OK here since the result is not used. (a = b).callAMember(); // would be ok if member is not also a // member of bool. if (a := b) { } // Here := is required (or extra ())Uh, I hope I didn't suggest having two different assignment operators tosame thing, with one being used in tests and the other one not. That'sjustwrong.It is the same operator... just that the short version is more restricted... but if := is always used, it is OK for me... But still allowing = would allows easier porting of existing code as := would be seldom required...I _did_ suggest replacing the bare equal sign (=) assignment operator withacolon-equal (:=) a la Pascal, and I stand by that. To anger several of you further allow me to go several steps farther over the edge and suggestredoingall the assignment operators to include a colon... = becomes := += becomes :+ -= becomes :- *= becomes :* /= becomes :/ %= becomes :% <<= becomes :<<!= becomes :! &= becomes :& |= becomes :| ^= becomes :^ ~= becomes :~ Did I forget any?= becomes :>>If not for D, then for the language that is sure to come after D.I think that != should not be here. Does != means not equal (i.e. <>). This is a comparison and not an assignment!!! I think those changes are essentially useless and will make porting code a lot harder... And they are less visible (= is easier to spot than : in code)Oh, oh, oh -- I just had an even whackier idea... Howsabout we require something to tell the compiler that we really do wantto dothe assignment in the test? Like: [safe] if ( x = y ) ... ;If we have such a think, then we would like to be able to uses it in other context where like: - comparison or assignment between signed/unsigned - possible truncation - no break in a switch case (hey I'm back on switch discussion!) - any other warnings What I dislike with your solution is that it is not possible to apply the attribute only to a part on an expression... so in complex situations we might uses safe for one thing and hide another problem... $,?,...) that would modify the warnings that the compiler would normally give: We could have for example as prefix: : This is an assignment operator prefix ? This is a conditionnal operator prefix implicit conversion) This is a free (unsafe) operator prefix (allows more conversions like double to int, most anything to bool, base to derived...) $ Handle null object Some examples: if (a $== b) { } // Ok even if a, b or both are null if (a ?= b) { } // Is a equal to b if (a := b) { } assignment and test int i; double d; unsigned u; i = d; // Ok, allows truncation and other less safe conversion if (i == u) { } // No warning for comparing signed/unsigned -u; // No warning for negating an unsigned. base[] ba; derived[] de; Note that some case like just above are not very usefull for regular code but might be interesting in template code where we might be more or less restrictive in some cases. to indicate if we we want to be safer than usual (almost no conversion allowed) or allows more automatic conversions to happen automatically (for example converting a double to an int as in: void f( int i) { ... } f(25.5);John Boucher The King had Humpty pushed.
Sep 16 2003
"Ian Woollard" <Ian_member pathlink.com> ha scritto nel messaggio news:bk5nri$14cm$1 digitaldaemon.com...[...] The default behaviour is really unsafe. I would suggest a 'nobreak' statement for cases where you really do want the codetofall through; otherwise the compiler probably should fail to compile(possiblyswitcheable off with a compiler option.)I vote for that too. And BTW, Walter, while we're on the subject... how about multiple-value case labels, a la VB? switch (x) { case 0: ... case 1, 3, 5: ... case 2, 4, 6 to 10: // or 6..10 as in Pascal, or [6, 10] or whatever ... case is < 1: // see comments on this one below ... case 11, 13 to 15, is > 16: // All together now! ... default: // no, I'm not proposing a "case else" :) } While all other forms are simply short for writing more labels, the "is" form really requires the switch to be compiled as it was a series of if's, with the difference that part of the if expression has already been evaluated. The syntax would be "is <relational operator> <expression>" If the switched-on expression is an object, overloaded operators might be used (provided it's not already so); in this case, "case is <obj_reference_or_null>" would compare pointers instead of checking object equality. Note that I'm following the "is" operator proposal here... OK, just daydreaming maybe... I suppose that optimizing such a thing would be rather hard... anyway I tried... Ric
Sep 16 2003
I'd like to see a nobreak statement, but I absolutely hate to see a compiler option that basically changes the language. If a D program is valid then it should always be valid. And if it is not then the compiler shouldn't accept it, no matter what switches you pass. Otherwise we will end up with two different types of D programs (the auto-fall-through and the nobreak-required one) that are not source compatible. Stuff like that should be avoided from the very beginning, so there should be a definite decision on wether nobreak is required or not.[...] The default behaviour is really unsafe. I would suggest a 'nobreak' statement for cases where you really do want the code to fall through; otherwise the compiler probably should fail to compile (possibly switcheable off with a compiler option.)I vote for that too.And BTW, Walter, while we're on the subject... how about multiple-value case labels, a la VB?I think that is a nice idea. And it would also make the nobreak requirement less of a hassle, since most fall through cases are really multi-value cases (i.e. the same code body for all cases).switch (x) { case 0: ... case 1, 3, 5: ... case 2, 4, 6 to 10: // or 6..10 as in Pascal, or [6, 10] or whatever ... case is < 1: // see comments on this one below ...Is the last 'case' consistent with the proposed use of the "is" operator as a replacement for ===? Wouldn't this mean that if x is an object, then the pointer would be compared with 1?If the switched-on expression is an object, overloaded operators might be used (provided it's not already so); in this case, "case is <obj_reference_or_null>" would compare pointers instead of checking object equality. Note that I'm following the "is" operator proposal here...One thing to consider is that case statements involving objects and overloaded operators make it impossible for the compiler to check wether they are non-overlapping. E.g. class X; X c1; X c2; X c3; switch(somevalue) { case < c1: ... break; case [c2..c3]: ... break; } How should the compiler check wether there isn't a value v < c1 that is also >=c2 and <=c3? Now that I think more about it, I think retrofitting switch to become as powerful as if is probably not a good idea at all. Lets face it, the switch statement is really only an optimization to help the compiler generate efficient code. If switch was as powerful as if, then there would be no additional optimization possibilities and the whole statement would be pretty useless. [Oh the irony ;)]. Hauke
Sep 16 2003
In article <bk6n5l$11j6$1 digitaldaemon.com>, Hauke Duden wrote:Now that I think more about it, I think retrofitting switch to become as powerful as if is probably not a good idea at all. Lets face it, the switch statement is really only an optimization to help the compiler generate efficient code. If switch was as powerful as if, then there would be no additional optimization possibilities and the whole statement would be pretty useless. [Oh the irony ;)].Of course, you *could* make the switch statement a generalization of the old one without losing optimizations. Just define switch so that switch (<expr>) { case <c11>, <c12>: <statement1> case <c2>: <statement2> ... default: <statementn> } is be semantically equivalent to (ignoring fallthroughs for a moment, they'd have to be implemented with gotos or sth like that) typeof <expr> tmp = <expr>; if ((tmp == <c11>) || (tmp == <c12>)) { <statement1> } else if (tmp == <c2>) { <statement2> } else { <statementn> } The compiler will in this case have to recognize the "old-style" switch statements (where all cases are constant and maybe not overlapping), which should be trivial, and perform the usual optimizations on them. More complex statements (where some case is non-constant) are implemented as an if-elseif-etc-else statement. -Antti
Sep 16 2003
Antti Sykäri wrote:Of course, you *could* make the switch statement a generalization of the old one without losing optimizations.<snip>The compiler will in this case have to recognize the "old-style" switch statements (where all cases are constant and maybe not overlapping), which should be trivial, and perform the usual optimizations on them. More complex statements (where some case is non-constant) are implemented as an if-elseif-etc-else statement.I don't know. To me this seems to be a feature that complicates the the language (and the compiler) with not much of a real benefit. If you need if-capabilities, why not use if? You might need a temporary variable to store the "switch value", but that is really the only downside I see. Upsides of leaving the switch-case statement simple are: - less complicated compiler - no need to invent new syntax to express <,>,<=, is-in-interval [a..b], ]a..b], [a..b[, ]a..b[ etc. - You can instantly be certain that you are looking at "flat" code (i.e. code where no operator overloads and stuff like that are involved) when you see a switch statement. I still think a multi-case statement would be nice, though. It would only be syntactic sugar for multiple cases with a fallthrough, of course, but this is something that would probably actually be useful in everyday programming. Especially if "nobreak" is required to fall through to the next case statement. Hauke
Sep 16 2003
In article <bk6vo2$1sdp$1 digitaldaemon.com>, Hauke Duden wrote:Antti Sykäri wrote:The compiler might be slightly more complicated, or then again it could actually be even simpler or as simple. A quick'n'dirty compiler might implement "switch" simply by translating it to an if-else sequence, and an optimizing compiler could do as the optimizing C compilers do, if all values in case statements are known at compile time. On the other hand: - there would be less problems with: - "Why can't I use struct values/classes/enums/your-arbitrary-expression-here in the switch statement?" - And what the heck is so special about those that they can't be evaluated at runtime like everything else? - added ease for the maintenance programmer... For example, consider that you have an interactive environment which is used to "frobnicate" and "gref" and the older version also supported some features that now are deprecated. You might write a simple interpreter for it like this: char[] kw = read_keyword(); switch (kw) { case "frobnicate": do_frob(); break; case "gref": do_gref(); break; case "quit": quit(); break; case "xixaxa_xoxaxa_xuxaxa": // FALL THROUGH case "kirje": printf("Sorry, command %d is no longer supported.\n", kw); print_help(); break; default: printf("Unknown command %d\n", kw); break; printf_help(); } Interpreter works fine. Now your manager comes into the picture and says: "I need that localized in 10 languages, ASAP. Oh yeah, the keywords need to be localized too." So you decide to localize the whole codebase by first automatically extracting all the strings that exist in the program (say, 100000 lines) with a perl script and then search-and-replacing each string, for example, "xyzzy" with localize("xyzzy"). localize() is a global function that replaces xyzzy with whatever is appropriate in the current locale. "Yeah that's simple", you say to your manager, "I'll take at most a couple of hours to do the search & replace and write the localization code" Then you do it (15 minutes it takes), and result is: switch (kw) { case localize("frobnicate"): dothis(); break; case localize("gref"): ...etc... } You start doing manual, repetitive, error-prone work: converting switch statements to if-else statements. At the end of the week your boss asks "What took you so long? By the way, we need the localization in an other branch of the software delivered to customer X two months ago, but I guess it's simple to do since you already did it" and there we go again... This is just an extreme example of how orthogonal language features can be useful. Sometimes real life can be extreme, too. To summarize, what I hoped earlier was that the mechanics of the "switch" statement would be driven by its semantics rather than its implementation (switch is often compiled as a table lookup, using linear search, hashing or even binary search, and for that reason they have been restricted to constant values of basic types -- because it's easiest to produce efficient code for them. Dunno what D compiler does with string literal lookups, though -- is it a trade secret? <grin>). I admit that being driven by implementation can make you feel sort of close to machine, which is sort of a good thing. Efficient-looking constructs often end up being efficient, too. This is part of the fascination in C. But sometimes you want things that Just Work, and we seem to be steadily traveling away from the bare metal anyway. I'm not suggesting making "switch" work on non-constant values would be a critical feature in the language, just some extra cream on the cake. This issue also touches things like reference to bit[], template arguments of different types, what-have-you. There should be as few special cases as possible.Of course, you *could* make the switch statement a generalization of the old one without losing optimizations.<snip>The compiler will in this case have to recognize the "old-style" switch statements (where all cases are constant and maybe not overlapping), which should be trivial, and perform the usual optimizations on them. More complex statements (where some case is non-constant) are implemented as an if-elseif-etc-else statement.I don't know. To me this seems to be a feature that complicates the the language (and the compiler) with not much of a real benefit. If you need if-capabilities, why not use if? You might need a temporary variable to store the "switch value", but that is really the only downside I see.Upsides of leaving the switch-case statement simple are: - less complicated compiler - no need to invent new syntax to express <,>,<=, is-in-interval [a..b], ]a..b], [a..b[, ]a..b[ etc.Sorry if you got me wrong, I didn't mean to propose those. I believe the language has too much syntax already. Adding extra operators feels the same as adding new icons to your favorite Windows program's toolbar. Some Windows programs that I use have tons of tiny icons and I don't have the faintest of what they actually do. Just having a button with a caption would suit me fine, thank you. Or, in the programming language area, a method or function which does the same. For example, "x is_in_interval [1..5]" might mean 1 <= x && x <= 5 (or < 5 if you want it the Dijkstra way) in a hypothetical programming language. Why not have [1..5] denote a constant of type Range, and have a method Range.has(int)? Then you'd have "[1..5].has(x)". But why end there if you can have "Range(1, 5).has(x)". (Well, maybe operators are sometimes nice after all.)- You can instantly be certain that you are looking at "flat" code (i.e. code where no operator overloads and stuff like that are involved) when you see a switch statement.Hmm, strangely I have no special desire to be certain that there wouldn't be operator overloading or other features that belong into a modern language. I should be able to trust that the operators I use are overloaded properly (so that they convey the right semantics). Oops, what a rant this grew up to be... better stop and do something useful for a while ;) -Antti
Sep 16 2003
Then you do it (15 minutes it takes), and result is: switch (kw) { case localize("frobnicate"): dothis(); break; case localize("gref"): ...etc... }Here I suppose you would like that every items be compared in turn for equality with kw until a match is found... And what we should do if I want to uses something else than operator== for the comparison ? It would then be nice to be able to pass a function/delegate/function object/... that would be used for the comparison similat to what we have in C++ STL where many algorithm accept user predicate...This is just an extreme example of how orthogonal language features can be useful. Sometimes real life can be extreme, too. To summarize, what I hoped earlier was that the mechanics of the "switch" statement would be driven by its semantics rather than its implementation (switch is often compiled as a table lookup, using linear search, hashing or even binary search, and for that reason they have been restricted to constant values of basic types -- because it's easiest to produce efficient code for them. Dunno what D compiler does with string literal lookups, though -- is it a trade secret? <grin>).Well if this is allowed then it mean that the compiler would be able to find duplicate case which is a usefull feature of case... and I'm not sure that having different rules on how it works depending on weither the expression is a constant or not is a good idea... This simple change allows for bugs that would be caused by misusing a variable a constant (for example using a enum variable instead of a value defined inside of the enum). If switch is extended in such a way, a would prefer a solution where would have to explictly specify a function for comparing the values: bool myfunction(char[] expr, char[] caseValue) { return localize(caseValue) == expr; } switch (x, myfunction) // I'm not sure of the syntax for passing a function // or a delegate or sothing similar { case "unlocalized1" : break; case "unlocalized2" : break; } That way, we would be able to localize without replacing the switch but global find and replace won't works either... But that syntax has some limitations: First it won't works for range or condition like < 5. Second, we can check only one thing at a time... So while it is better, the solution is not as general as someone could like it.... And I think it would be preferable to have a syntax that allows ranges like < 5 or 1..5. Maybe we should always uses a..b syntax and uses special constant min/max or -INF/+INF for range that are not bounded on one side: case min..5 : case -INF..5 : Also it would be interesting to support range that include/exclude limit for types that are not finite (double, strings,...). Maybe, [, (, ) and ] should be used as required... or we might have a postfix + or - to indicate if the value is include or not: case 5+..9.5+ : // from 5 (not included to to 9.5 included) case 5..9 : // 5 to 9 both ends included case 5-..9+ : // Idem case 5+..9-- : // 5 to 9, ends not includedFor example, "x is_in_interval [1..5]" might mean 1 <= x && x <= 5 (or < 5 if you want it the Dijkstra way) in a hypothetical programming language. Why not have [1..5] denote a constant of type Range, and have a method Range.has(int)? Then you'd have "[1..5].has(x)". But why end there if you can have "Range(1, 5).has(x)". (Well, maybe operators are sometimes nice after all.)If we allows something like Range(1, 5).has(x), then it means that when we look at the switch expression, we will never be sure that only that is used to evaluate which case to select... since one could uses a function with side effect or reference a variable that is not is the switch expression. IMO we should only extent switch to support range and support any type of constant (if this is not already the case). The main difference between if/else and a switch is that a switch is supposed to select a case from an expression... And I thing that we should be able to have arbitrary expression for each case as this would allows side-effect and subtle bugs... caused by the fact that the cases do not depend only on the expression... Also, I think that a switch should be independant on the order of each case and reordering them should not changes the output but might only affect the performance if the optimizer assumes that first cases are more probable...
Sep 16 2003
Antti Sykäri wrote:The compiler might be slightly more complicated, or then again it could actually be even simpler or as simple. A quick'n'dirty compiler might implement "switch" simply by translating it to an if-else sequence, and an optimizing compiler could do as the optimizing C compilers do, if all values in case statements are known at compile time.<convincing arguments snipped> You argue your case well ;). I can now see the benefits of having a generalized switch statement.Sorry if you got me wrong, I didn't mean to propose those. I believe the language has too much syntax already.Agreed.For example, "x is_in_interval [1..5]" might mean 1 <= x && x <= 5 (or < 5 if you want it the Dijkstra way) in a hypothetical programming language. Why not have [1..5] denote a constant of type Range, and have a method Range.has(int)? Then you'd have "[1..5].has(x)". But why end there if you can have "Range(1, 5).has(x)". (Well, maybe operators are sometimes nice after all.)This raises a new problem, though. To be able to apply complicated operators with the current condition-syntax you would have to have some special constant that represents the switch-value. I.e. something like: switch(someFunc()) { case switchval>=5 && switchVal<=9: do something... } However, this might make nested switch statements a little hard to understand. switch(someFunc()) { case switchval>=5 && switchVal<=9: switch(someOtherFunc()) { case switchVal.coolCheckFunc(): /*this is the NEW value*/ someStuff(); break; } break; } Add some more nested layers and things are certain to get complicated quickly. I think if you wanted to do something like this you'd have to be able to specify a name for the switch value. Like an imaginary const variable. Something like this: switch(someFunc() as sval1) { case sval1 >= 5 .... } Hauke
Sep 17 2003
In article <bk97c1$1dfi$1 digitaldaemon.com>, Hauke Duden wrote:Antti Sykäri wrote:I try not to post only my opinions but also the thinking process behind them. This is because I've found that suggestions and propositions that have no convincing arguments behind them tend to be easily dismissed. The result is what you see also in this posting: longish rants :) (Sorry, I've yet to learn the skill of Concise Ranting!)The compiler might be slightly more complicated, or then again it could actually be even simpler or as simple. A quick'n'dirty compiler might implement "switch" simply by translating it to an if-else sequence, and an optimizing compiler could do as the optimizing C compilers do, if all values in case statements are known at compile time.<convincing arguments snipped> You argue your case well ;).I can now see the benefits of having a generalized switch statement.But the question remains, how generalized? In my previous posting, I talked about generalizing switch; now I'll wear another hat and present some arguments for restricting it. I believe that the switch statement could be generalized to some extent. But it must still stay limited: it should fundamentally play the same role as the classic "switch". My view is that the meaning of switch should be "evaluate an expression, and based on the result, select one of the legs and execute its code". Whether the values that the result is compared against are constant -- or even if they are distinct -- is to me irrelevant. Actually, when you think of it, even falling through is a pretty useless idea. In the good old C language, falling through was not just a hack but very useful hack indeed. It was an easy way to get multiple values to do the same thing. A modern language might want to replace falling through with switching on multiple values, either in the set form or in the range form: (syntax would be hypothetical here) case 1, 2, 3: do_this() or case 1..4, 9: do_that() or even, if we have the dynamical version List(int) some_numbers; some_numbers.insert(1, 2, 3); Set(int) other_numbers; other_numbers.insert(1,2,3,4,9); case some_numbers: do_this() case other_numbers: do_that() List(T) and Set(T) should of course be the D's natural representations for those concepts. Or maybe just any classes that model a certain concept: it should have a "contains" or "has" method which checks the existence of a value in itself. Maybe I'm getting away from the planet earth a bit too fast but hey -- if you accepted things like "case 1, 2, 3" and ranges, why not accept dynamic sets and ranges as well? I'm not really sure of this. It might look like a crude hack to treat sets, ranges and values the same, but my judgement fails me here... Let's consider this thing for a second. Well, range and set are ok. Range is just a specialized sort of set. You can say "(1..5).has(1)", and "Set(int) x = makeSet(1, 2); x.has(1)", and it makes sense. But can you do 1.has(1)? Obviously testing of membership (or equivalence) would have to be like in the foreach case - compiler magic if it's a basic type, and applying of function such as "has()" or "equals()"/"==" if it's a user-defined type. But which one to apply? Use operator "==" only if the combination has no matching "has" method? Use "has" only if there is no matching operator "=="? If neither matches, it's an error -- what if both match? It might be a dark corner in the language; reminds me of Russell's paradox in mathematics ("Define a set "well-behaved" if it doesn't contain itself as an element. Consider the set S of all well-behaved sets. Is S well-behaved?"). Or then again it might cause no harm at all in practice. (Designers of popular languages, starting from C, have always known when to cut corners.) We were talking about fallthrough, right? Someone might point out that fallthrough has other uses besides doing the thing X on several values: occasionally you could even "reuse" some code by first doing something in the first leg and then continuing to the second one. But the value of this is dubious at least from the viewpoint of code maintenance. The programmer that follows your footsteps is likely to add another leg between those two. Murphy's laws state that the bug will manifest itself the day when he quits the company and there we have it: a maintenance nightmare. Nowadays a good programmer would probably extract the common code to a function (or to a local function as we have such a splendid feature in D) and avoid the problem. Oh what the heck, maybe you could leave fallthrough there -- when you try to prohibit something, the programmers will work hard trying to dig around the limitations and the result often ends up even dirtier than expected. (In this case I can't imagine anything uglier than a goto statement to the next leg. I'm certain, though, that there are more talented programmers out there who can crank out something so horrible and unmaintainable that it would truly be a work of art.) Now about the distinctness of the values-to-be-checked-against of the switch statement, mentioned in another follow-up. Originally it was also useful to enforce distinctness of the different values on which to switch upon: including two or more switch legs with the same constant value would be pointless and misleading. (And ill-defined as long as the semantics are defined as "THE switch statement that matches X will be executed") Although this view can be also disputed. I recently had a switch statement similar to: switch (keycode) { case middle_button: case fire: case some_other_button: ... } On platform X, middle_button and fire were on different keys, and, consequently, keycodes. However, on platform Y, there were no special "middle button" so the mappings were changed and "fire" ended denoting to the same integer value as "middle_button". Compile-time error was the result. So this was worked around along the lines of: switch (keycode) { case middle_button: #ifndef PLATFORM_Y case fire: #endif case some_other_button: ... } As you can see it's not a pretty solution. And then some comments:This raises a new problem, though. To be able to apply complicated operators with the current condition-syntax you would have to have some special constant that represents the switch-value. I.e. something like: switch(someFunc()) { case switchval>=5 && switchVal<=9: do something... }Oh yeah, now let's reiterate that the current posting is all about "I didn't want to do that much after all. Just a little bit syntactic would be fine and then I be nice and quiet" ;-) Seriously, I wouldn't necessarily go as far as to allow _any_ expression to occur in a case "label". It would make the usual cases (equivalence and belonging into a set, another container, or a range) too wordy and the whole switch statement merely a if-elseif-then in a disguise. But it's a good idea to have access to the statement-to-be-switched. Now that I think about it, I've often wanted access to it.However, this might make nested switch statements a little hard to understand. switch(someFunc()) { case switchval>=5 && switchVal<=9: switch(someOtherFunc()) { case switchVal.coolCheckFunc(): /*this is the NEW value*/ someStuff(); break; } break; }As an aside, did you read http://lambda.weblogs.com/discuss/msgReader$8721 (about referring to things with pronouns)? Anyway I propose the following syntax: switch (int result = someFunc()) { ... case 2, 3, 5, 7: printf("%d is a small prime\n", result); ... } that also the for loop uses and someone, I think, also proposed it for the while and/or if statements. That might be good for consistency, hint, hint :) Certainly, you can do the same if you introduce the variable immediately before the statement, but hey, why can I introduce a variable in a for statement but not elsewhere? That's one of the questions that no one should be able to ask. -Antti
Sep 17 2003
In article <slrnbmhp8u.bkq.jsykari pulu.hut.fi>, Antti =?iso-8859-1?Q?Syk=E4ri?= says...Actually, when you think of it, even falling through is a pretty useless idea. In the good old C language, falling through was not just a hack but very useful hack indeed. It was an easy way to get multiple values to do the same thing. A modern language might want to replace falling through with switching on multiple values, either in the set form or in the range form: -AnttiHere you seem to refer only to falling-through from an empty case, which I agree would be made clearer by allowing multiple values on the case. One of the few reasons I _do_ use fall-through is in something like the following, where having four of something means that there are also three of it: import c.stdio ; void main ( char[][] args ) { int lines = 0 ; char[] outfile = "stdout" ; switch ( args.length ) { case 4 : { // Parse the "#lines" parameter } case 3 : { // Parse the "outfile" parameter } case 2 : { // Parse the "infile" parameter } default : { printf ( "\nYou did not specify enough parameters\nSyntax: DTEST infile [ outfile [ #lines ]]" ) ; } } return ; } John Boucher The King had Humpty pushed.
Sep 17 2003
Antti Sykäri wrote:But the question remains, how generalized? In my previous posting, I talked about generalizing switch; now I'll wear another hat and present some arguments for restricting it.<snip>Maybe I'm getting away from the planet earth a bit too fast but hey -- if you accepted things like "case 1, 2, 3" and ranges, why not accept dynamic sets and ranges as well? I'm not really sure of this. It might look like a crude hack to treat sets, ranges and values the same, but my judgement fails me here... Let's consider this thing for a second.You seem to alternate between wanting to have an uber-powerful switch and at the same time keep it as simple as it currently is. I have noticed the same tendency in myself. However, then I realized that switch really has only one major benefit over if-else: it is easy to express SIMPLE conditional branching. If you introduce switch-case with dynamic lists or sets you end up not only having a switch that is as powerful as if, but it becomes a foreach and if rolled into one! I really think having such "fat" statements in a programming language (even a high level one) is a bad idea. You'd end up becoming some sort of CISC language (to borrow a term from CPU design) that tries to provide direct solutions for every problem on earth. We already have two primitives (foreach and if) that can handle these cases. We should try to keep the language simple and not introduce too many ways to express the same thing. And if someone really needs this all the time then he could always write a template to do it. In my opinion this kind of specialized solution should be part of a library, not of the language. Another point against a uber-switch is that in my experience long, nested switch statements can be pretty hard to read. The syntax is just a little too different from all other constructs (no curly braces for the code blocks, no round braces for conditions, break denotes the end, etc.). And combining this with the way many people (do not) handle indentation I'd hate to see switch used everywhere where foreach and if may actually be a better choice.Actually, when you think of it, even falling through is a pretty useless idea. In the good old C language, falling through was not just a hack but very useful hack indeed. It was an easy way to get multiple values to do the same thing. A modern language might want to replace falling through with switching on multiple values, either in the set form or in the range form:As another post in this thread noted, fallthrough CAN sometimes be useful. However, I agree that these cases are pretty rare and multi-cases could replace the need for fallthrough in many circumstances. Maybe it isn't such a bad idea to just kick out fallthrough completely. The few instances where multi-cases aren't adequate could still easily be solved with if-else and overall readability would be improved. About your idea of allowing non-distinct case-statements: I'm not sure this is such a good idea. I guess in many cases non-distinctness would be a bug (say, using the wrong constant). Silently executing more than one branch just seems unintuitive to me. If we wouldn't have the requirement to easily port C/C++ code to D (do we really have it?) I would like to suggest to ditch the classic switch statement completely and introduce a new construct with different syntax that is more consistent with the rest of the language. This would also solve the problem that different fallthrough behaviour might confuse C/C++ programmers, since it is immediately recognizable as a different thing. Maybe something like this: branch(expression) { on(1) someFunc(); on(2,3,5..8) { a=7; dostuff(a,true); } } Hmmm. I think the syntax would probably need some work, but it would have some benefits: - the on-blocks are real code blocks. Adding local variables to them works in the same way as it does anywhere else. - break is not used in this construct, so it could actually be used to break out of an outer loop. This is something that I quite often wanted to do in C++. Ok, it is not THAT much of an issue in D anymore, since we can break with a label but being able to do it without an explicit label improves readability, since it is immediately clear which loop is referred to. But since I don't see any chance that switch is ditched there is no real point to argue for such a statement anyway ;). About having a name for the switch value:As an aside, did you read http://lambda.weblogs.com/discuss/msgReader$8721 (about referring to things with pronouns)? Anyway I propose the following syntax: switch (int result = someFunc()) { ... case 2, 3, 5, 7: printf("%d is a small prime\n", result); ... }I thought about something like that too. However, this would introduce a real variable, not just a name for a value. There may be some performance issues with that. Also, you'd have to make this variable const to prevent it from being changed inside the switch statement => more things to check for the compiler. Hauke
Sep 18 2003
Way to go! erik In article <bkbunb$29u9$1 digitaldaemon.com>, Hauke Duden says... <snip>Maybe it isn't such a bad idea to just kick out fallthrough completely. The few instances where multi-cases aren't adequate could still easily be solved with if-else and overall readability would be improved.</snip> <snip>If we wouldn't have the requirement to easily port C/C++ code to D (do we really have it?) I would like to suggest to ditch the classic switch statement completely and introduce a new construct with different syntax that is more consistent with the rest of the language. This would also solve the problem that different fallthrough behaviour might confuse C/C++ programmers, since it is immediately recognizable as a different thing. Maybe something like this: branch(expression) { on(1) someFunc(); on(2,3,5..8) { a=7; dostuff(a,true); } }</snip>
Sep 18 2003
Way to go!I also like that syntax... Clear, no problem with it (fall-through) and enough different... And if in some situation we need more power, we should also provide a distinct syntax for that feature instead of have the same keyword used for too much things (like static in C++). On thing that I would like is the ability to specify that every possible values must be handled in the branch statement so that if a value is added to an enum, we would be able to have an error for all branch that do not handled that new value... and we also need the default case... So we have 3 possibilities: - partial set of cases checked - partial set of cases checked and a default - all cases must be checked (implies no default) ondefault for default case or maybe else section: exclusive_branch(expression) same as above but all cases must be present Maybe we should still support the old switch for C compatibility but uses branch whenever possible... That way, we have best of both world, elegant modern syntax and safe when using brand, compatibility and a bit more power when using switch... (for exemple possibility of fall-through).I would like to suggest to ditch the classic switch statement completely and introduce a new construct with different syntax that is more consistent with the rest of the language. This would also solve the problem that different fallthrough behaviour might confuse C/C++ programmers, since it is immediately recognizable as a different thing. Maybe something like this: branch(expression) { on(1) someFunc(); on(2,3,5..8) { a=7; dostuff(a,true); } }
Sep 18 2003
I like that branch too. If we had that, after a few years once D gains enough popularity, old C-style switch support could be dropped. ;) Sean "Philippe Mori" <philippe_mori hotmail.com> wrote in message news:bkdh98$1evd$1 digitaldaemon.com...Maybe we should still support the old switch for C compatibility but uses branch whenever possible... That way, we have best of both world, elegant modern syntax and safe when using brand, compatibility and a bit more power when using switch... (for exemple possibility of fall-through).
Sep 19 2003
Anyway I propose the following syntax: switch (int result = someFunc()) { ... case 2, 3, 5, 7: printf("%d is a small prime\n", result); ... } that also the for loop uses and someone, I think, also proposed it for the while and/or if statements. That might be good for consistency, hint, hint :) Certainly, you can do the same if you introduce the variable immediately before the statement, but hey, why can I introduce a variable in a for statement but not elsewhere? That's one of the questions that no one should be able to ask.I agree with that extension.... For dynamic cases, it is OK provided that we still allows the compiler to validate static cases and we define the interaction between them. For maintenance nightmare, I agree that function should normally be used... but sometimes, it is easy to optimize the code just by using fallthrough but if not supported directly, one can uses goto for those rare cases where performance or code size do really matter... Also in some specific situations, it might be interesting to evaluate all cases, reevaluate the switch, goto a specific case, fallthrough,... In fact for event-driven programming where we have to handled some messages, having some controls might be interesting... but in those case, one would not only want to check a signle member for a few conditions (like the control ID and the message ID for an UI event)... And in those case, it might even be interesting to be able to return a value that indicate if the event was handled or not and having that used to decide if we fall-through the next case... In C++, event handling often uses switch or if/else with sometime a bool to indicate if the event was handled: BEGIN_MAP ON_CDM(id, fn1) ON_EXIT(fn2) ON_MESSAGE(msgId, ctrlId, fn3) END_MAP where each function returns true if the event was handled... Since in D, there are no such macro and such tables are common and usefull, it might be interesting to extend switch to be able to do something similar: switch (event) { case is_cmd(id, event) : break if fn1(); case is_exit(event) : break if fn2(event); }
Sep 18 2003
I just thought of another thing: If we allow function calls in the case value we cannot prevent side effects that mess with the intended semantics. E.g. class X { bool stupid=false; bool isCool() { stupid=true; return false; } bool isStupid() { return stupid; } } X x; switch(x as sval) { case sval.isCool(): someFunc(); break; case sval.isStupid(): someOtherFunc(); break; } The outcome of this switch statement depends on the order the case statements are evaluated. Of course, that is up to the compiler, so things could work with one compiler version but might not with another. The following code snippet has the same problem: if(x.isCool() || x.isStupid()) as does someFunc(x.isCool(),x.isStupid()) Does D define an evaluation order for conditional statements and/or function arguments? I think it would be important to have the switch statement behave in a way that is consistent to that. Hauke
Sep 17 2003
The example below is hypothetical, I believe. I believe that nothing that is too difficult to enforce should be enforced by the language. If a programmer really does what he does in isCool(), he gets all he deserves... The issue here is "side-effects inside functions that are supposed to be side-effectless". There's not much point trying to do that, and it's really difficult to do it by mistake. A good design principle I've bounced into: "Protect the programmer from Murphy, not Macchiavelli" I believe I first heard it in context of C++, but I can't find the original source here. google finds an explanation at: http://photon.poly.edu/~hbr/cs903-F00/lib_design/notes/advanced.html "We can distinguish between to kinds of protection a design can provide: protection against Murphy, and protection against Macchiavelly. Murphy describes an user that makes occasionally mistakes, while Macchiavelli describes an user that willingly tries to get around the protection mechanism. Protection against Macchiavelli in C++ is almost impossible, as C-style type casts and the example above illustrates. An effective but expensive solution would be opaque pointers and a link library manipulating the opaque pointer, where the sources of the underlying data are not published. Here, we discuss usually solutions that protect against Murphy." Paul Graham goes even further and claims that programming languages should be designed for the smart people. http://www.paulgraham.com, lots of articles, "Five Questions about Language Design" might not be a bad place to start with. -Antti In article <bk97sm$1e9m$1 digitaldaemon.com>, Hauke Duden wrote:I just thought of another thing: If we allow function calls in the case value we cannot prevent side effects that mess with the intended semantics. E.g. class X { bool stupid=false; bool isCool() { stupid=true; return false; } bool isStupid() { return stupid; } } X x; switch(x as sval) { case sval.isCool(): someFunc(); break; case sval.isStupid(): someOtherFunc(); break; } The outcome of this switch statement depends on the order the case statements are evaluated. Of course, that is up to the compiler, so things could work with one compiler version but might not with another. The following code snippet has the same problem: if(x.isCool() || x.isStupid()) as does someFunc(x.isCool(),x.isStupid()) Does D define an evaluation order for conditional statements and/or function arguments? I think it would be important to have the switch statement behave in a way that is consistent to that. Hauke
Sep 17 2003
Antti Sykäri wrote:The issue here is "side-effects inside functions that are supposed to be side-effectless". There's not much point trying to do that, and it's really difficult to do it by mistake. A good design principle I've bounced into: "Protect the programmer from Murphy, not Macchiavelli"Actually, my main point was to keep it consistent with the rest of the language. Bad programmers will always find a way to mess up, but I'd at least like the language to behave the same in regard to side effects in all contexts. Hauke
Sep 18 2003
"Antti Sykäri" <jsykari gamma.hut.fi> ha scritto nel messaggio news:slrnbmdvgs.jlv.jsykari pulu.hut.fi...The compiler will in this case have to recognize the "old-style" switch statements (where all cases are constant and maybe not overlapping), which should be trivial, and perform the usual optimizations on them. More complex statements (where some case is non-constant) are implemented as an if-elseif-etc-else statement.Great! Now I'm curious about Walter's opinion, he's the compiler guy after all... Ric
Sep 16 2003
Oh, so we're going to start specifying a new syntax for the switch statement? Cool! Because I recently decided that I would always put braces around the statements in cases (to more obviously group them visually) (I also always use braces with ifs, fors, and whiles -- more coherent visual presentation) I propose that they be required, so howsabout: switch ( expr ) { case ( 1 ) { .. break; } case ( 2 , 3 ) { .. nobreak; } default { .. break; } } An additional benefit of this syntax is that it removes the colon, thereby freeing it up for use in the assignment operator(s). John Boucher -- Quite contrary The King had Humpty pushed.
Sep 16 2003
"John Boucher" <John_member pathlink.com> ha scritto nel messaggio news:bk7e08$6u2$1 digitaldaemon.com...Because I recently decided that I would always put braces around thestatementsin cases (to more obviously group them visually) (I also always use braceswithifs, fors, and whiles -- more coherent visual presentation) I propose thattheybe required, so howsabout: switch ( expr ) { case ( 1 ) { .. break; } case ( 2 , 3 ) { .. nobreak; } default { .. break; } } An additional benefit of this syntax is that it removes the colon, thereby freeing it up for use in the assignment operator(s).Besides, this way each case is a scope of its own and may have local variables. I often use braces this way in switch statements and surely wouldn't mind them being required. Ric
Sep 18 2003
"Hauke Duden" <H.NS.Duden gmx.net> ha scritto nel messaggio news:bk6n5l$11j6$1 digitaldaemon.com...Is the last 'case' consistent with the proposed use of the "is" operator as a replacement for ===? Wouldn't this mean that if x is an object, then the pointer would be compared with 1?Nice and right objection. I blind-copied it from VB. "is" might as well be omitted altogether.One thing to consider is that case statements involving objects and overloaded operators make it impossible for the compiler to check wether they are non-overlapping.I think the first matching case should apply.Now that I think more about it, I think retrofitting switch to become as powerful as if is probably not a good idea at all. Lets face it, the switch statement is really only an optimization to help the compiler generate efficient code. If switch was as powerful as if, then there would be no additional optimization possibilities and the whole statement would be pretty useless. [Oh the irony ;)].The switch statement is a logical construct; the fact that it *can* be optimized, e.g. using jump tables, pertains to the compiler's internals. I don't think that such extreme optimizations are needed any longer on today's machines, or at least they could be sacrificed (at least partially; DMD _is_ an optimizing compiler, it does not optimize only switch statements...) if the advantages in code readability and maintainability are found to be more important than the loss in pure speed. Besides, when the switch expression is really an expression (as opposed to a single variable) it is computed once, which doesn't happen with chained if's... Ric
Sep 16 2003
Please not that the suggested syntax leaves both 'break' and 'nobreak' redundant. erik In article <bk6fbt$8n2$1 digitaldaemon.com>, Riccardo De Agostini says..."Ian Woollard" <Ian_member pathlink.com> ha scritto nel messaggio news:bk5nri$14cm$1 digitaldaemon.com...[...] The default behaviour is really unsafe. I would suggest a 'nobreak' statement for cases where you really do want the codetofall through; otherwise the compiler probably should fail to compile(possiblyswitcheable off with a compiler option.)I vote for that too. And BTW, Walter, while we're on the subject... how about multiple-value case labels, a la VB? switch (x) { case 0: ... case 1, 3, 5: ... case 2, 4, 6 to 10: // or 6..10 as in Pascal, or [6, 10] or whatever ... case is < 1: // see comments on this one below ... case 11, 13 to 15, is > 16: // All together now! ... default: // no, I'm not proposing a "case else" :) } While all other forms are simply short for writing more labels, the "is" form really requires the switch to be compiled as it was a series of if's, with the difference that part of the if expression has already been evaluated. The syntax would be "is <relational operator> <expression>" If the switched-on expression is an object, overloaded operators might be used (provided it's not already so); in this case, "case is <obj_reference_or_null>" would compare pointers instead of checking object equality. Note that I'm following the "is" operator proposal here... OK, just daydreaming maybe... I suppose that optimizing such a thing would be rather hard... anyway I tried... Ric
Sep 16 2003
"Erik Baklund" <Erik_member pathlink.com> ha scritto nel messaggio news:bk6vgp$1rn2$1 digitaldaemon.com...Please not that the suggested syntax leaves both 'break' and 'nobreak' redundant.Of course: break should be implied. Thanks for pointing that out. Ric
Sep 16 2003
I am sorry that my statement came out a bit garbeled. My intension was to say that I appreciated your syntax because it suggested the possibility of a cleaner implementation of the 'switch' statement. It even leaves both keywords 'break' and 'nobreak' redundant. The reason is that the semantics of both keywords could be interpreted to be implicit in the syntax: switch(n) { case 4 [..mplicit nobreak..], 5: { // Some code } [..implicit break..] default: { // Some code } } The benefit I saw was was that : 1) A new keyword 'nobreak' is not needed. Fallback (nobreak) through null-code is allowed, when cases are stated on the same line. 2) The old keyword 'break' is not needed because it could be decided always to be be implicit. Thus, it would not any longer be possible to create a bug by forgetting 'break' because there is no 'break' to forget. 3) Clean value/code-block mapping is enforced. i.e. implicit breaks would prevent programmers from fragmenting code blocks into conditional parts and spread them over several 'case'es (a bad practice that is possible in C/C++). erik In article <bk714l$20ms$2 digitaldaemon.com>, Riccardo De Agostini says..."Erik Baklund" <Erik_member pathlink.com> ha scritto nel messaggio news:bk6vgp$1rn2$1 digitaldaemon.com...Please not that the suggested syntax leaves both 'break' and 'nobreak' redundant.Of course: break should be implied. Thanks for pointing that out. Ric
Sep 16 2003
I am sorry that my statement came out a bit garbeled. My intension was to say that I appreciated your syntax because itsuggested thepossibility of a cleaner implementation of the 'switch' statement. It even leaves both keywords 'break' and 'nobreak' redundant. The reason is that the semantics of both keywords could be interpreted tobeimplicit in the syntax: switch(n) { case 4 [..mplicit nobreak..], 5: { // Some code } [..implicit break..] default: { // Some code } } The benefit I saw was was that : 1) A new keyword 'nobreak' is not needed. Fallback (nobreak) throughnull-codeis allowed, when cases are stated on the same line. 2) The old keyword 'break' is not needed because it could be decidedalways tobe be implicit. Thus, it would not any longer be possible to create a bugbyforgetting 'break' because there is no 'break' to forget. 3) Clean value/code-block mapping is enforced. i.e. implicit breaks would prevent programmers from fragmenting code blocks into conditional partsandspread them over several 'case'es (a bad practice that is possible inC/C++).erikAnd how do you handle fall-through? With a goto (maybe something like goto case(4) where one would give the expression that indicate the target; if this expression is constant, the compiler can make a direct jump; otherwise we switch on that new value). This would even be more powerfull that any other solution I have seen presented: int some_value = ...; switch (some_expr()) { case 1 : goto case(some_value); // redo the switch with that new value. case 2: goto case(1); // compile-time jump to case 1 case 3 : do_something(); goto case(default); // default is a special value for jumping to default default: do_something_else(); }
Sep 16 2003
In article <bk823t$2cpv$1 digitaldaemon.com>, Philippe Mori says...Oh, yeah, specific jumping rather than falling-through _is_ better. Let's get rid of fall-through altogether... in the next language maybe. Boy, I'd better start keeping a list. John Boucher -- Maybe not so contrary after all The King had Humpty pushedI am sorry that my statement came out a bit garbeled. My intension was to say that I appreciated your syntax because itsuggested thepossibility of a cleaner implementation of the 'switch' statement. It even leaves both keywords 'break' and 'nobreak' redundant. The reason is that the semantics of both keywords could be interpreted tobeimplicit in the syntax: switch(n) { case 4 [..mplicit nobreak..], 5: { // Some code } [..implicit break..] default: { // Some code } } The benefit I saw was was that : 1) A new keyword 'nobreak' is not needed. Fallback (nobreak) throughnull-codeis allowed, when cases are stated on the same line. 2) The old keyword 'break' is not needed because it could be decidedalways tobe be implicit. Thus, it would not any longer be possible to create a bugbyforgetting 'break' because there is no 'break' to forget. 3) Clean value/code-block mapping is enforced. i.e. implicit breaks would prevent programmers from fragmenting code blocks into conditional partsandspread them over several 'case'es (a bad practice that is possible inC/C++).erikAnd how do you handle fall-through? With a goto (maybe something like goto case(4) where one would give the expression that indicate the target; if this expression is constant, the compiler can make a direct jump; otherwise we switch on that new value). This would even be more powerfull that any other solution I have seen presented: int some_value = ...; switch (some_expr()) { case 1 : goto case(some_value); // redo the switch with that new value. case 2: goto case(1); // compile-time jump to case 1 case 3 : do_something(); goto case(default); // default is a special value for jumping to default default: do_something_else(); }
Sep 16 2003
Nonono .. no goto! This thread discusses two topics in paralell. One discussion is about "how to prevent codemakers doing mistakes with 'switch'", the other one is "what can we add of neat features to the 'switch' statement". Since I am supervizing programmers and seing real project money being spent on fixing mistakes associated with 'switch', my comments was about how make the 'switch' statement safer. There are two common mistakes with 'switch' that I wanted to prevent: 1) Forgetting to add 'break'. 2) Excersize the bad practise of implementing conditional excecution paths using 'switch'. The latter practise is often less successful and should be done by regular 'if' statements. To me the 'switch' statement is a state to code-block mapping tool. The state being codified in the 'switch' argument. Compiled languages most often constrains the switch argument to be an integer so that hardware supported fast lookup can be leveraged. With that perspective in mind, the only time one should wish to leave out the 'break', is when several states are mapping to the same code-block. In other words, 'fall-through' should only be permitted through empty code blocks. Your syntax "case 2, 3, 5:" expressed this so elegantly, and suddenly 'nobreak' and 'break' was needed no more. Kind regards, Erik In article <bk823t$2cpv$1 digitaldaemon.com>, Philippe Mori says...I am sorry that my statement came out a bit garbeled. My intension was to say that I appreciated your syntax because itsuggested thepossibility of a cleaner implementation of the 'switch' statement. It even leaves both keywords 'break' and 'nobreak' redundant. The reason is that the semantics of both keywords could be interpreted tobeimplicit in the syntax: switch(n) { case 4 [..mplicit nobreak..], 5: { // Some code } [..implicit break..] default: { // Some code } } The benefit I saw was was that : 1) A new keyword 'nobreak' is not needed. Fallback (nobreak) throughnull-codeis allowed, when cases are stated on the same line. 2) The old keyword 'break' is not needed because it could be decidedalways tobe be implicit. Thus, it would not any longer be possible to create a bugbyforgetting 'break' because there is no 'break' to forget. 3) Clean value/code-block mapping is enforced. i.e. implicit breaks would prevent programmers from fragmenting code blocks into conditional partsandspread them over several 'case'es (a bad practice that is possible inC/C++).erikAnd how do you handle fall-through? With a goto (maybe something like goto case(4) where one would give the expression that indicate the target; if this expression is constant, the compiler can make a direct jump; otherwise we switch on that new value). This would even be more powerfull that any other solution I have seen presented: int some_value = ...; switch (some_expr()) { case 1 : goto case(some_value); // redo the switch with that new value. case 2: goto case(1); // compile-time jump to case 1 case 3 : do_something(); goto case(default); // default is a special value for jumping to default default: do_something_else(); }
Sep 17 2003
In article <bk9vjp$2fel$1 digitaldaemon.com>, Erik Baklund says...Nonono .. no goto! There are two common mistakes with 'switch' that I wanted to prevent: 1) Forgetting to add 'break'. 2) Excersize the bad practise of implementing conditional excecution paths using 'switch'. The latter practise is often less successful and should be done by regular 'if' statements. Kind regards, ErikI think I agree. I definitely agree with your first assertion, that there should be no default fall-through. And I also like the idea of a case having a list of values. It seems to me that the switch statement was created to make the coding of an ugly series of _simple_ ifs easier to read (and providing a performance boost as well). So I'm less enthusistic about trying to make it handle an ugly series of _tricky_ ifs. (On the other hand, it seems that allowing ranges would allow the use of reals in the switch statement.) However, given that we are used to fall-through, it seems like there should be a way to allow that. Adding a nobreak or something will provide that. Buuut... another problem with fall-through is what happens when a new case is added in the middle of a switch and gets fallen-through to accidently -- another rookie mistake. That's why _I_ now think that a goto of some sort to _specify_ which case to execute next is a good thing. And I think that it would need to be a construct that will only allow gotoing to a lexically later case. (And, yes, my opinion has changed from a day or two ago.) I'm just not sure what to suggest for the gotoing syntax, how about: nextcase ( 1 ) ; // Or whatever Upon further reflection, I also think that such a statement would only be allowed once in a case, as the last line of course. If something trickier is required, don't use a switch. Having said that, mightn't it still be legal to use a regular goto to invalidate the whole switch concept anyway? As in... switch ( expr ) { case 2 : .. gobackhere: // Naughty naughty // Could be an endless loop too! .. case 1 : .. goto gobackhere ; } So, yes, rework the switch statement to reduce errors and improve clarity, but _not_ to add functionality. John Boucher The King had Humpty pushed.
Sep 17 2003
And I also like the idea of a case having a list of values.Me too...However, given that we are used to fall-through, it seems like thereshould be away to allow that. Adding a nobreak or something will provide that.Buuut...another problem with fall-through is what happens when a new case is addedinthe middle of a switch and gets fallen-through to accidently -- anotherrookiemistake. That's why _I_ now think that a goto of some sort to _specify_ which casetoexecute next is a good thing. And I think that it would need to be aconstructthat will only allow gotoing to a lexically later case. (And, yes, myopinionhas changed from a day or two ago.) I'm just not sure what to suggest for the gotoing syntax, how about: nextcase ( 1 ) ; // Or whatever Upon further reflection, I also think that such a statement would only be allowed once in a case, as the last line of course. If something trickierisrequired, don't use a switch.No it should be allowed anywhere as it is allowed to return from anywhere inside a function... It should be possible to contionally go to another case.Having said that, mightn't it still be legal to use a regular goto toinvalidatethe whole switch concept anyway? As in... switch ( expr ) { case 2 : .. gobackhere: // Naughty naughty // Could be an endless loop too! .. case 1 : .. goto gobackhere ; } So, yes, rework the switch statement to reduce errors and improve clarity,but_not_ to add functionality.So, in resume, what we would like is breaking by default and allowing branching to a case by value... Otherwise, same as current switch (for ex. we are still able to uses goto if we really want).
Sep 18 2003
"Riccardo De Agostini" <riccardo.de.agostini email.it> ha scritto nel messaggio news:bk6fbt$8n2$1 digitaldaemon.com...I vote for that too.Except for the compiler option, I meant. Let D be D. Ric
Sep 16 2003
And BTW, Walter, while we're on the subject... how about multiple-valuecaselabels, a la VB? switch (x) { case 0: ... case 1, 3, 5: ... case 2, 4, 6 to 10: // or 6..10 as in Pascal, or [6, 10] or whatever ... case is < 1: // see comments on this one below ... case 11, 13 to 15, is > 16: // All together now! ... default: // no, I'm not proposing a "case else" :) }For me, multiple values is OK and range also (with either syntax) But for the is operator, I'm not sure... I think those case could be handled if the default case with regular if... OTOH, this might be a good solution particulary if we add the nodefault (see below). IMO, is is surperfluous. We could have < 1 or .. 1 or [ , 10] but maybe it should be required just to ensure that there are no unintended errors... I think that each range should be mutually exclusive so that it is illegal to have the same value twice once explicit and once in a range. We should have also an option to specify that each possible values must have a label for case when all cases must be handled. This would typically be usefull for enumerations where we might want to ensure that all values appears. switch (enumVar) { case e1 : break; case e2 : doSomething(); nobreak; case e3 : doSomethingElse(); break; nodefault: // All valid value for the type must appears in the switch } This would be great for cases where an enum is needed and we must handle all case...
Sep 16 2003
"Philippe Mori" <philippe_mori hotmail.com> wrote in message news:bk7gft$gju$1 digitaldaemon.com...We should have also an option to specify that each possible values must have a label for case when all cases must be handled. This would typically be usefull for enumerations where we might want to ensure that all values appears.A good idea, but this is already addressed in D where the default case, if not specified, is to throw an exception.
Nov 26 2003
Walter wrote:Not that I'm against that, but it seems a little inconsistent. What happened to that "we cannot change the semantics of switch because that would confuse C/C++ coders" rule? Throwing an exception where C/C++ would just continue is a rather big difference, isn't it? If that rule has been dropped - how about adding an implicit break as well? ;) HaukeWe should have also an option to specify that each possible values must have a label for case when all cases must be handled. This would typically be usefull for enumerations where we might want to ensure that all values appears.A good idea, but this is already addressed in D where the default case, if not specified, is to throw an exception.
Nov 26 2003
If that rule has been dropped - how about adding an implicit break as well? ;)Seconded! C "Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:bq2t8k$qe1$1 digitaldaemon.com...Walter wrote:ifWe should have also an option to specify that each possible values must have a label for case when all cases must be handled. This would typically be usefull for enumerations where we might want to ensure that all values appears.A good idea, but this is already addressed in D where the default case,not specified, is to throw an exception.Not that I'm against that, but it seems a little inconsistent. What happened to that "we cannot change the semantics of switch because that would confuse C/C++ coders" rule? Throwing an exception where C/C++ would just continue is a rather big difference, isn't it? If that rule has been dropped - how about adding an implicit break as well? ;) Hauke
Nov 26 2003
Wow! That's a *really*, *REALLY* bad idea. If one is porting some code which very rarely uses the default case - it's largely irrelevant whether that's benign or a bug - it may easily escape the test cases, and "sometime later", in production code, an exception will be thrown which has never been anticipated and therefore never been handled. This is about the very best/worst example I could possibly think of in the debate between compile-time and runtime error-handling. Rather than causing me 30 seconds in development time, I am up for an unknown, and potentially huge, cost sometime after deployment. Is D really wanting to be a serious systems language? Yours, in a state of stupefaction MatthewWe should have also an option to specify that each possible values must have a label for case when all cases must be handled. This would typically be usefull for enumerations where we might want to ensure that all values appears.A good idea, but this is already addressed in D where the default case, if not specified, is to throw an exception.
Nov 26 2003
In article <bq2vi2$tqd$1 digitaldaemon.com>, Matthew Wilson says...I agree! Why nobody else is complaining? was this discussed before? Since the first time I was surprised with the exception I just automatically type in an empty default. AntWow! That's a *really*, *REALLY* bad idea.We should have also an option to specify that each possible values must have a label for case when all cases must be handled. This would typically be usefull for enumerations where we might want to ensure that all values appears.A good idea, but this is already addressed in D where the default case, if not specified, is to throw an exception.
Nov 26 2003
I havent come accross it, but mark this up as another complaint ! :). C "Ant" <Ant_member pathlink.com> wrote in message news:bq33o3$140q$1 digitaldaemon.com...In article <bq2vi2$tqd$1 digitaldaemon.com>, Matthew Wilson says...ifWe should have also an option to specify that each possible values must have a label for case when all cases must be handled. This would typically be usefull for enumerations where we might want to ensure that all values appears.A good idea, but this is already addressed in D where the default case,I agree! Why nobody else is complaining? was this discussed before? Since the first time I was surprised with the exception I just automatically type in an empty default. Antnot specified, is to throw an exception.Wow! That's a *really*, *REALLY* bad idea.
Nov 26 2003
"Ant" <Ant_member pathlink.com> wrote in message news:bq33o3$140q$1 digitaldaemon.com...In article <bq2vi2$tqd$1 digitaldaemon.com>, Matthew Wilson says...ifWe should have also an option to specify that each possible values must have a label for case when all cases must be handled. This would typically be usefull for enumerations where we might want to ensure that all values appears.A good idea, but this is already addressed in D where the default case,I do that too, and don't like it much. I do, however, like how an exception is thrown if the end of a non-void function is reached. By the way, I like how switch cases fall through silently; probably for the same reasons as Walter. I proposed that we use a new keyword for cases that automatically break when a new case is found, such as: switch(s) { case 3: falls through bcase 4: auto-breaks at next case, bcase, or default }I agree! Why nobody else is complaining? was this discussed before? Since the first time I was surprised with the exception I just automatically type in an empty default. Antnot specified, is to throw an exception.Wow! That's a *really*, *REALLY* bad idea.
Nov 26 2003
Vathix wrote:I do that too, and don't like it much. I do, however, like how an exception is thrown if the end of a non-void function is reached.Huh? How can that happen? Doesn't the compiler check at compile time that there is a return statement in each possible path? All C/C++ compilers I know will at least issue a warning in such a case (though it should be an error). DMD doesn't do that? Hauke
Nov 26 2003
either _break_ or _goto_ another case, no fall through, zip, nada, zilch. And the compiler tells you when you try. <stump> I would also prefer it be required that the statements in a _case_ be placed in a block surrounded by braces _{}_ to better group them visually. Same with _if_, _while_, _for_, _do_ ... anywhere where it is currently required *sometimes*, it should be required *all the time*. Easier reading, I expect easier parsing/lexing whatever. It shouldn't be too difficult to write a script to go through the C code and add the otherwise extraneous stuff (doesn't hurt the C any) before attempting to port it. </stump>
Nov 26 2003
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:bq3blg$1fvl$1 digitaldaemon.com...Vathix wrote:exceptionI do that too, and don't like it much. I do, however, like how anThe problem is it's not possible to do this 100%. Consider the trivial case: int foo(int x) { while (x) { blahblah if (blah blah) return 3; } } The programmer may know that x is never 0, but the compiler can't figure it out. Hence it stuffs a throw at the end. Sure, it's a contrived example, but I've seen cases of this in real code.is thrown if the end of a non-void function is reached.Huh? How can that happen? Doesn't the compiler check at compile time that there is a return statement in each possible path? All C/C++ compilers I know will at least issue a warning in such a case (though it should be an error). DMD doesn't do that?
Nov 26 2003
Walter wrote:"Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:bq3blg$1fvl$1 digitaldaemon.com...Vathix wrote:I do that too, and don't like it much. I do, however, like how anThe problem is it's not possible to do this 100%. Consider the trivial case: int foo(int x) { while (x) { blahblah if (blah blah) return 3; } } The programmer may know that x is never 0, but the compiler can't figure it out. Hence it stuffs a throw at the end. Sure, it's a contrived example, but I've seen cases of this in real code.VC6 issues a warning in that case: "warning C4715: 'foo' : not all control paths return a value" I agree that such a case should be allowed without requiring an explicit return that you know will never be reached. But can't the compiler issue a warning at compile time in addition to the runtime exception. I quite often write functions that return a boolean that (should) end with "return true;". However, I sometimes simply forget the last return (having just dealt with complicated error-cases the normal case return sometimes slips my mind). I like it if the compiler warns me about that. Maybe that warning could be made optional with a commandline switch? Hauke
Nov 27 2003
why allow it? this is bad code, at least issue a warning because someone someday will call foo() with a 0int foo(int x) { while (x) { blahblah if (blah blah) return 3; } } The programmer may know that x is never 0, but the compiler can't figure it out. Hence it stuffs a throw at the end. Sure, it's a contrived example, but I've seen cases of this in real code.VC6 issues a warning in that case: "warning C4715: 'foo' : not all control paths return a value" I agree that such a case should be allowed without requiring an explicit return that you know will never be reached.
Nov 27 2003
Mark T wrote:Well, if 0 is an invalid argument, then throwing an exception would be the right thing to do. This might save the programmer the need to do it manually. Though now that I think about it ... in almost all cases I can imagine one would want the exception to be something like InvalidArgError. If you get UnexpectedEndOfFunction (or whatever is thrown) that sounds like there is a bug in the function, instead of a bug in the calling code. And these cases should be rare enough that an "unnecessary" return statement wouldn't really amount to much of a hassle. I also just realized that we will never get Walter to add warnings to the compiler, so I'll switch sides. I'm all for making it an error now ;). It's still much better than having the compiler not complain at all about such a thing... Haukewhy allow it? this is bad code, at least issue a warning because someone someday will call foo() with a 0int foo(int x) { while (x) { blahblah if (blah blah) return 3; } } The programmer may know that x is never 0, but the compiler can't figure it out. Hence it stuffs a throw at the end. Sure, it's a contrived example, but I've seen cases of this in real code.VC6 issues a warning in that case: "warning C4715: 'foo' : not all control paths return a value" I agree that such a case should be allowed without requiring an explicit return that you know will never be reached.
Nov 27 2003
figure itint foo(int x) { while (x) { blahblah if (blah blah) return 3; } } The programmer may know that x is never 0, but the compiler can'texample, butout. Hence it stuffs a throw at the end. Sure, it's a contrivedsomedaywhy allow it? this is bad code, at least issue a warning because someoneI've seen cases of this in real code.VC6 issues a warning in that case: "warning C4715: 'foo' : not all control paths return a value" I agree that such a case should be allowed without requiring an explicit return that you know will never be reached.will call foo() with a 0Agreed. It has to be an error.
Nov 27 2003
Me too... I think that syntax should be more strict in D than in C/C++, so I agree with Walter's PoW: a piece of code is either acceptable or not i.e. gives error or not (ok, viceversa ;). For this case I think the return should be explicitely given or, at least, to state that any function will return (implicitely) the initialization type value (the variable's default value). Anyway, interesting subject. BTW in Matlab, the warning is like: Warning: some output arguments never assigned in function xxx. In article <bq5lir$1v0j$1 digitaldaemon.com>, Matthew Wilson says...figure itint foo(int x) { while (x) { blahblah if (blah blah) return 3; } } The programmer may know that x is never 0, but the compiler can'texample, butout. Hence it stuffs a throw at the end. Sure, it's a contrivedsomedaywhy allow it? this is bad code, at least issue a warning because someoneI've seen cases of this in real code.VC6 issues a warning in that case: "warning C4715: 'foo' : not all control paths return a value" I agree that such a case should be allowed without requiring an explicit return that you know will never be reached.will call foo() with a 0Agreed. It has to be an error.
Nov 28 2003
"Hauke Duden" <H.NS.Duden gmx.net> wrote in messageMaybe that warning could be made optional with a commandline switch?I need to write a short paper on why I philosophically object to warnings! (This issue comes up repeatedly.)
Nov 27 2003
Walter wrote:"Hauke Duden" <H.NS.Duden gmx.net> wrote in messageI know the way you feel about this. Maybe you're right and the necessity for warnings are a sign of a badly designed language. However - and I don't mean to be trolling here, just speaking my mind - if you refuse to employ one particular kind of workaround for a design flaw then you shouldn't just invent a new workaround, but instead try to find a real solution for the flaw! This kind of exception is just a kind of warning (actually more like an error) that is issued at runtime, instead of compile time. IMHO that's a step in the wrong direction. HaukeMaybe that warning could be made optional with a commandline switch?I need to write a short paper on why I philosophically object to warnings! (This issue comes up repeatedly.)
Nov 27 2003
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:bq60t4$2gol$1 digitaldaemon.com...This kind of exception is just a kind of warning (actually more like an error) that is issued at runtime, instead of compile time. IMHO that's a step in the wrong direction.You're right that it would be better to do it at compile time, but like array bounds checking, it is impossible to do at compile time.
Nov 27 2003
In article <bq5g2i$1m63$1 digitaldaemon.com>, Walter says..."Hauke Duden" <H.NS.Duden gmx.net> wrote in messageYou forget you philosophically object to compiler options, too. I suggest to add it to your paper. CiaoMaybe that warning could be made optional with a commandline switch?I need to write a short paper on why I philosophically object to warnings! (This issue comes up repeatedly.)
Nov 28 2003
"Roberto Mariottini" <Roberto_member pathlink.com> wrote in message news:bq7g8g$1n6g$1 digitaldaemon.com...In article <bq5g2i$1m63$1 digitaldaemon.com>, Walter says...warnings!"Hauke Duden" <H.NS.Duden gmx.net> wrote in messageMaybe that warning could be made optional with a commandline switch?I need to write a short paper on why I philosophically object toLOL! They're both related, that's for sure.(This issue comes up repeatedly.)You forget you philosophically object to compiler options, too. I suggest to add it to your paper.
Nov 28 2003
"Walter" <walter digitalmars.com> wrote in message news:bq3pkp$24v0$1 digitaldaemon.com...case:Huh? How can that happen? Doesn't the compiler check at compile time that there is a return statement in each possible path? All C/C++ compilers I know will at least issue a warning in such a case (though it should be an error). DMD doesn't do that?The problem is it's not possible to do this 100%. Consider the trivialint foo(int x) { while (x) { blahblah if (blah blah) return 3; } } The programmer may know that x is never 0, but the compiler can't figureitout. Hence it stuffs a throw at the end. Sure, it's a contrived example,butI've seen cases of this in real code.It is conceivable that due to a HW glitch or Act of God that x actually turns up 0 once every 4 billion runs. If you can't be 200% sure, I would rather the compiler bitch at me, or automatically insert some code that will never run, bloating my app by a few bytes, than take the chance of having execution fall off the end of my function. It *is* possible to do this 100% if you require that all return paths are explicitly marked and handled, i.e. reject the above code as erroneous due to potential execution path problems. The problem with the above function is that it's probably written inside out anyway... maybe it should have been written as this: int foo(int x) { while (x) { blahblah if (blah blah) break; } return 3; } or this: int foo(int x) { if (x) do { blahblah }while (!blah blah); return 3; } Sean
Nov 28 2003
"Sean L. Palmer" <palmer.sean verizon.net> wrote in message news:bq7boo$1g93$1 digitaldaemon.com...It is conceivable that due to a HW glitch or Act of God that x actually turns up 0 once every 4 billion runs.I think that protecting against CPU hardware failures is beyond the scope of the language.If you can't be 200% sure, I would rather the compiler bitch at me, or automatically insert some code thatwillnever run, bloating my app by a few bytes, than take the chance of having execution fall off the end of my function.It does the latter now <g>.It *is* possible to do this 100% if you require that all return paths are explicitly marked and handled, i.e. reject the above code as erroneous due to potential execution path problems.Several C++ compilers do emit warnings for such. I find those warnings to be irritating rather than useful. For example, they will warn about: int foo() { while (1) { .... return ...; } } where it is *not possible* for the code to fall off the end, but the warning happens, and to get rid of it I have to put in a return statement that will never execute. I find being forced to add code that will never execute to be inelegant and potentially confusing. Hence my motivation for having D ensure that it never executes by raising an exception if it does, but that doesn't muck up the source code.
Nov 28 2003
"Walter" <walter digitalmars.com> wrote in message news:bq897h$2s6v$1 digitaldaemon.com..."Sean L. Palmer" <palmer.sean verizon.net> wrote in message news:bq7boo$1g93$1 digitaldaemon.com...ofIt is conceivable that due to a HW glitch or Act of God that x actually turns up 0 once every 4 billion runs.I think that protecting against CPU hardware failures is beyond the scopethe language.havingIf you can't be 200% sure, I would rather the compiler bitch at me, or automatically insert some code thatwillnever run, bloating my app by a few bytes, than take the chance ofareexecution fall off the end of my function.It does the latter now <g>.It *is* possible to do this 100% if you require that all return pathsdueexplicitly marked and handled, i.e. reject the above code as erroneousbeto potential execution path problems.Several C++ compilers do emit warnings for such. I find those warnings toirritating rather than useful. For example, they will warn about: int foo() { while (1) { .... return ...; } } where it is *not possible* for the code to fall off the end, but thewarninghappens, and to get rid of it I have to put in a return statement thatwillnever execute. I find being forced to add code that will never execute tobeinelegant and potentially confusing. Hence my motivation for having Densurethat it never executes by raising an exception if it does, but thatdoesn'tmuck up the source code.So your argument is that because some code analysers in some compilers are less than perfect, you'll change the language itself, and push out error detection from fool-proof and efficient compile-time to unexpected, surprising and inefficient runtime. I am running out of adjectives on this one. Suffice to say, this is going to be really good ammunition for D-etractors.
Nov 28 2003
Matthew Wilson wrote:I am running out of adjectives on this one. Suffice to say, this is going to be really good ammunition for D-etractors.D-ctatorship rules. :> Walter may be right, but when using Delphi i found that adding a line to shut up the code analyzer is not necessarily a bad idea. It expresses explicitly what would have happened anyway, so it improves the readability, not worsens it. Especially it fits well with assertions being a language feature in D. E.g. if one knows that a conditional on which execution path depends is necessarily zero, then one could either eliminate checks, or add an assert(var==0), which should be treated by a code analyzer as if variable was just assigned zero! -eye
Nov 29 2003
"Ilya Minkov" <minkov cs.tum.edu> wrote in message news:bqac81$2rl3$1 digitaldaemon.com...E.g. if one knows that a conditional on which execution path depends is necessarily zero, then one could either eliminate checks, or add an assert(var==0), which should be treated by a code analyzer as if variable was just assigned zero!You're right that one advantage to having assertions as part of the syntax is that the optimizer can potentially make use of the additional information.
Nov 29 2003
Walter wrote:You're right that one advantage to having assertions as part of the syntax is that the optimizer can potentially make use of the additional information.I definately didn't mention the optimizer. What i meant is that assertion is a semantic guarantee, which may be very important to the code flow analysers, such as the one which makes sure that a function always retuns. So that if an analyser says that there is some execution path which doesn't return - it needn't place an assertion there, instead the programmer may place an assertion which makes sure that this code path never enters, which should be enough to keep the complaining analyser quite, and would make program flow more explicit. Let me also quote Roberto Mariottini, since his idea is of a similar nature:BTW, what about user defined enum? Can the compiler know whether all enum constants are used inside a switch, and signal to the programmer when some are missing and there is not a default?Even enum being stored within an int, this information translates into an implicit assertion (i==enumval1)||(i==enumval2)||(... which need not be generated in target code, but such information can be worked in by analysers as such. I'm probably bad at expressing my thoughts today, so i'll try to formulate it more thoroughly and post up some other time. This branch also goes somewhat off the thread topic, which was about switch. My opinion is that i completely agree with status quo which guards against unintended misuse very well, but i also find it an interesting option for a switch to requiere a default case, unless the code analyser could prove that such a case cannot happen. I would also vote for a requierement of explicit continue statement, which would give some symmetry with loops, but it may not be an option to you... -eye
Nov 30 2003
"Ilya Minkov" <minkov cs.tum.edu> wrote in message news:bqdqmg$1hen$1 digitaldaemon.com...Walter wrote:Well, that's just what an optimizer is: a code flow analyzer. <g>You're right that one advantage to having assertions as part of the syntax is that the optimizer can potentially make use of the additional information.I definately didn't mention the optimizer. What i meant is that assertion is a semantic guarantee, which may be very important to the code flow analysers,such as the one which makes sure that a function always retuns. So that if an analyser says that there is some execution path which doesn't return - it needn't place an assertion there, instead the programmer may place an assertion which makes sure that this code path never enters, which should be enough to keep the complaining analyser quite, and would make program flow more explicit.You've just described the general idea of how optimizers work.Let me also quote Roberto Mariottini, since his idea is of a similarnature:Even if all the enum values are accounted for, it's certainly possible the user cast some other value into the enum type.BTW, what about user defined enum? Can the compiler know whether all enum constants are used inside a switch, and signal to the programmer when some are missing and there is not a default?Even enum being stored within an int, this information translates into an implicit assertion (i==enumval1)||(i==enumval2)||(... which need not be generated in target code, but such information can be worked in by analysers as such.This branch also goes somewhat off the thread topic, which was about switch. My opinion is that i completely agree with status quo which guards against unintended misuse very well, but i also find it an interesting option for a switch to requiere a default case, unless the code analyser could prove that such a case cannot happen. I would also vote for a requierement of explicit continue statement, which would give some symmetry with loops, but it may not be an option to you...Part of my reluctance to do that is implict fallthrough just has never been an issue for me in 25 years of programming. But the implicit default:break; has bitten me many times!
Nov 30 2003
Part of my reluctance to do that is implict fallthrough just has neverbeenan issue for me in 25 years of programming. But the implicitdefault:break;has bitten me many times!I can honestly say that neither issue has hurt me once in, say, the last five years. But what've either of our cat's whiskers got to do with it. There aren't many people who spend as much time as we on the keyboard - lucky bleeders! - so my question is: do you want your language to be a desirable option only for those who've been bitten for hard enough and long enough in older curmudgeonlier languages. There aren't that many of us left; most have slothed off into middle management by now. Surely you want to appeal to younger programmers. Since universities are not teaching much worth absorbing these days, why not build things into your language that help people who are of intermediate level, rather than just doing the bits you deem are needed for you and those like you(/us)? 1. If every aspect of switch is explicit and compile-time, how many users of D will be hurt? 0 2. If things remain implicit and, worse, there is runtime handling of code-time errors, how many users of D will be hurt? Probably about 20-40% now. Probably about 90-95% of the eventual target user base. If I'm wrong about this, can someone please tell me. I don't want to hear about any individual wants personally, we've already gone through that already. (Personally, I'd rather have it precisely have the semantics of C's switch, but I'd rather have D robust and successful than have to type a few less keystrokes.) Just point out where I'm wrong with these projections. (Notwithstanding the inherent inaccuracies in the precise numbers). Matthew
Nov 30 2003
I think your numbers are spot on. For me, personally, it's been reversed. Missing default:assert(0); hasn't bitten me much, because any switch on an enum that I expect can grow already has a default:assert(0); written in explicitly. But the implicit fallthrough has bitten me so many times it makes me scream every time it happens (and it happens fairly frequently). I know that the C fallthru behavior ends up on many a FAQ, and if you took a poll of C users, they would rank it high on the list of bug sources, probably just a few rungs down from dangling pointers, memory leaks, and off-by-one errors. Sean "Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bqefkr$2dnm$1 digitaldaemon.com...longPart of my reluctance to do that is implict fallthrough just has neverbeenan issue for me in 25 years of programming. But the implicitdefault:break;has bitten me many times!I can honestly say that neither issue has hurt me once in, say, the last five years. But what've either of our cat's whiskers got to do with it. There aren't many people who spend as much time as we on the keyboard - lucky bleeders! - so my question is: do you want your language to be a desirable option only for those who've been bitten for hard enough andenough in older curmudgeonlier languages. There aren't that many of usleft;most have slothed off into middle management by now. Surely you want to appeal to younger programmers. Since universities arenotteaching much worth absorbing these days, why not build things into your language that help people who are of intermediate level, rather than just doing the bits you deem are needed for you and those like you(/us)? 1. If every aspect of switch is explicit and compile-time, how many usersofD will be hurt? 0 2. If things remain implicit and, worse, there is runtime handling of code-time errors, how many users of D will be hurt? Probably about 20-40% now. Probably about 90-95% of the eventual target user base. If I'm wrong about this, can someone please tell me. I don't want to hear about any individual wants personally, we've already gone through that already. (Personally, I'd rather have it precisely have the semantics ofC'sswitch, but I'd rather have D robust and successful than have to type afewless keystrokes.) Just point out where I'm wrong with these projections. (Notwithstandingtheinherent inaccuracies in the precise numbers). Matthew
Dec 01 2003
In article <bqe96t$24um$1 digitaldaemon.com>, Walter says...Well, that's just what an optimizer is: a code flow analyzer. <g>I was advocating something different: it makes sense to do this as part of semantic analysis process, and bug user with arbitrary conditions like "i'm not convinced this function returns" or "this switch may not cover a variable value range", as long as convincing the compiler usually takes only one line, which would also make code more explicit. I'm only speaking of my experiance that i found this practice quite convenient. (Delphi fans vote here!) You must also consider that D advocates a different development cycle than C++. Recompile often and early. In this context it makes sense that the compiler bugs you about something not so important and not the runtime, especally the compiler being so fast. Your disagreement has probably something to do with your oposition to warnings, since that's what compiler message class this kind of diagnostic could best refer to. You really have to put up a paper on that so that we understand you better.Even if all the enum values are accounted for, it's certainly possible the user cast some other value into the enum type.Should this be legal at all? If yes, then someone should take responsibility. Eother the cast has to take care that enum only gets a legal value by throwing an exception otherwise, or the programmer...Part of my reluctance to do that is implict fallthrough just has never been an issue for me in 25 years of programming. But the implicit default:break; has bitten me many times!And in the 5 years before the 25 years? You must also consider that you are an exceptional talent and a full-time programmer. I don't value language-specific skills that much... -eye
Dec 02 2003
"Ilya Minkov" <Ilya_member pathlink.com> wrote in message news:bqhnh3$15iv$1 digitaldaemon.com...I was advocating something different: it makes sense to do this as part of semantic analysis process, and bug user with arbitrary conditions like"i'm notconvinced this function returns" or "this switch may not cover a variablevaluerange", as long as convincing the compiler usually takes only one line,whichwould also make code more explicit. I'm only speaking of my experiancethat ifound this practice quite convenient. (Delphi fans vote here!)The trouble with 'may' is you wind up inserting some piece of cruft to get the compiler to pass it. That cruft is usually dead code, and since it does not contribute to the algorithm it serves merely to confuse the maintenance programmer. Two common pieces of such cruft are an extra return statement that's never executed, and supplying an initializer to a variable that is always overwritten before ever being read. Here's the extra initializer thing: int x; <= compiler demands that this needs an initializer if (...) x = 3; <= actual algorithmic initialization ... if (same condition as previous if) y = x; <= x is always initialized here to 3, but well-meaning but nagging compiler squawks it is possibly uninitialized. Argh. Inserting the extra initializer at the top just is confusing, as the maintenance programmer thinks "where is this value ever used? Looks like some sort of bug."You must also consider that D advocates a different development cycle thanC++.Recompile often and early. In this context it makes sense that thecompiler bugsyou about something not so important and not the runtime, especally thecompilerbeing so fast.I agree with pushing as much off into compile time as makes sense to. But if I go too far, then we've got Pascal, and I gave up on that language after discovering that 50% of my coding time was spent fighting the compiler's best efforts to stop me from writing the kind of code I wanted to write.Your disagreement has probably something to do with your oposition towarnings,since that's what compiler message class this kind of diagnostic couldbestrefer to. You really have to put up a paper on that so that we understandyoubetter.Perhaps I should rename "warnings" to "nags" and my rationale would be clearer <g>.theEven if all the enum values are accounted for, it's certainly possibleYes. A cast exists as an escape from the language's typing rules. Pascal didn't have a cast.user cast some other value into the enum type.Should this be legal at all?If yes, then someone should take responsibility. Eother the cast has totakecare that enum only gets a legal value by throwing an exception otherwise,orthe programmer...I expect the programmer to account for it, and if he fails to, hopefully the runtime will catch it and throw an exception.beenPart of my reluctance to do that is implict fallthrough just has neverdefault:break;an issue for me in 25 years of programming. But the implicitlanguage-specifichas bitten me many times!And in the 5 years before the 25 years? You must also consider that you are an exceptional talent and a full-time programmer. I don't valueskills that much...I make plenty of coding errors, just like all of us here.
Dec 05 2003
int x; <= compiler demands that this needs an initializer if (...) x = 3; <= actual algorithmic initialization ... if (same condition as previous if) y = x; <= x is always initialized here to 3, but well-meaning but nagging compiler squawks it is possibly uninitialized.and then someone else comes along and changes the code to int x; if ( cond ) { x=3; } ... if ( cond || other cond ) { y = x; } and without warning we have a bug that the compiler is not telling us about. one solution would be int x = int.init; to keep the compiler happy (just explicitly doing what should be done anyway) a better would be int x = undef; in which case the debug build should change to; int x = int.init; int__x_set = false; if ( cond ) { x = 3; __x_set = true; } .... if ( cond || other ) { // or if (cond). if ( !__x_set ) { throw new Error( "x not initialised", __FILE__, __LINE__ ); } y = x; } // in a release build the 'int x = undef', is just 'int x = int.init' ;
Dec 06 2003
<one_mad_alien hotmail.com> wrote in message news:bqsm17$287n$1 digitaldaemon.com...one solution would be int x = int.init; to keep the compiler happy (just explicitly doing what should be doneanyway) The compiler does this already implicitly if no initializer is given, then the optimizer usually optimizes it away as dead code.a better would be int x = undef;For floating point types, the default initializer is NAN, and the result of all the computations on x will then be NAN. Unfortunately, there is no NAN value for integral types.
Dec 08 2003
In article <bqs1ft$16i2$1 digitaldaemon.com>, Walter says..."Ilya Minkov" <Ilya_member pathlink.com> wrote in message(an excellent discussion deleted) If Walter succeeds in keeping the different phases of compiling separate, then that opens up (even commercial) possibilities for D. I could envision maybe getting an Open Source lexer, a commercial optimizer, and the code generator from a third place. Sort of like the OSI layer thing. This would of course only be possible if the layer interfaces were standardized. Then I could choose between a "nagging" or a "strict" front end, I could have an "errors only", "with warnings", "with remarks", or "with informative hints" front end, depending on whether the users are "absolute beginners" or "Ultra Pro Gurus". (There's more to this than just a verbosity level switch.) Heck, a university could even write front ends for different semester classes, and _especially_ one for non-CS-professors for their own work! For now, this implies that whatever error messages, or not, D this year generates is not all that important at the end of the day. Maybe we should concentrate more on actual language issues and other things with real long-term ramifications.
Dec 06 2003
I've had a hard time reading this thread. Instead of a discussion, this has more looked like Walter is getting an awful lot of flack for not revamping case functionality. I think that if a language implements exceptions, then with it goes inseparably the feature that whatever the programmer has not thought of (i.e. not caught), at least the runtime will offer a graceful and informative exit. In that same spirit, running off the end of functions, or not having a default part in a case structure, are things the programmer has not "thought of". So these should cause a runtime exception, period. If that is intentional (as in "we _know_" this'll never happen), then it is a small thing to inform the compiler that this is the case. Also, this informs the next programmer about our intentions, instead of having him think that we're just lazy SOBs. Breaks in case statements exist because it is customary to have both several different cases be handled by the same code, and also because it is usual that one case only does a one-liner, the rest of which is the same as some other case. Here the missing break turns very useful. Many things in D come from C(++), and many programmers will have to work both in D and C(++), at least in the immediately foreseeable future. Introducing gratuituos differences in the most basic things would only make their life hard. Since the motivations presented here (for making the changes in D) have not been able to show any major advantages, I think we should let this issue rest for now. (No flames for the following, please:) The fervor with which people have argued for not having to write a couple extra words, has made me think that maybe these guys do not do touch typing. I think such tings should not be permitted to influence the design of a serious language for professional programming. Even Bjarne Stroustrup has admitted that they made some changes to the language so that it would be "easier to write, in this (or that) particular context", and that some of these changes became dragstones and were regretted later. One excellent example would be declaring complicated pointer variables.
Nov 30 2003
Sorry to be obtuse, but I don't glean what your position is? C/C++ status quo, Walter's no-default exception, compiler-errors on any implicit parts? "Georg Wrede" <Georg_member pathlink.com> wrote in message news:bqd1l6$el6$1 digitaldaemon.com...I've had a hard time reading this thread. Instead of a discussion, this has more looked like Walter is getting an awful lot of flack for not revamping case functionality. I think that if a language implements exceptions, then with it goes inseparably the feature that whatever the programmer has not thought of (i.e. not caught), at least the runtime will offer a graceful and informative exit. In that same spirit, running off the end of functions, or not having a default part in a case structure, are things the programmer has not "thought of". So these should cause a runtime exception, period. If that is intentional (as in "we _know_" this'll never happen), then it is a small thing to inform the compiler that this is the case. Also, this informs the next programmer about our intentions, instead of having him think that we're just lazy SOBs. Breaks in case statements exist because it is customary to have both several different cases be handled by the same code, and also because it is usual that one case only does a one-liner, the rest of which is the same as some other case. Here the missing break turns very useful. Many things in D come from C(++), and many programmers will have to work both in D and C(++), at least in the immediately foreseeable future. Introducing gratuituos differences in the most basic things would only make their life hard. Since the motivations presented here (for making the changes in D) have not been able to show any major advantages, I think we should let this issue rest for now. (No flames for the following, please:) The fervor with which people have argued for not having to write a couple extra words, has made me think that maybe these guys do not do touch typing. I think such tings should not be permitted to influence the design of a serious language for professional programming. Even Bjarne Stroustrup has admitted that they made some changes to the language so that it would be "easier to write, in this (or that) particular context", and that some of these changes became dragstones and were regretted later. One excellent example would be declaring complicated pointer variables.
Nov 30 2003
In article <bqdjvu$1805$2 digitaldaemon.com>, Matthew Wilson says...Sorry to be obtuse, but I don't glean what your position is? C/C++ status quo, Walter's no-default exception, compiler-errors on any implicit parts?(I was aspiring to transcend the current issues themselves, but what the heck.) Walter's no-default exception. I'm thinking of a couple of different situations here. First of all, if D is your first language and you're just learning to use the switch statement, then you normally write the cases you know can happen, but leave the default out (since you 'covered all cases'). If that is ok, then no compiler warning or error. Well, the day comes when you didn't cover all cases, and then there will be a runtime exception. Now, the same thing happens with uncaught exceptions. Most of the time your new programs compile and run fine, but then there's the (say file not found) exception, all of a sudden. So you learn to cover your bases by taking care of also other than the obvious situations. By this process, you learn the language (and programming, as such) in a nice and efficient, natural way. Second, if you already are a (good) programmer, then you just have all your cases covered. Or, your functions just don't run off the end when you don't intend it. In this case all is fine. If, OTOH you are a 'bad programmer', then that happens to you all the time. Then you learn by mistake (which is a way of life for such people anyhow), until you either get it, or become a marketing person instead. ;-) If it were obligatory to write the default statement, then these latter folks would just learn that that is something that has to be there, and obviously the line would be 'default: break;'. When their programs don't work the way they expect, then they have a very hard time finding out why. And since the compiler couldn't warn or error about this, the only way is to figure out why it acts other than we wished. Making the default case obligatory therefore achieves nothing. But making it 'entirely non-obligatory' doesn't either. (I.e., not causing a runtime exception.) Of course it is embarrassing if a professionally developed program suddenly quits on a no-default exception. But worse is just running off the end with no warning. It's like sweeping your crap under the rug. The rant about touch typing was (among other things) for the guys who wanted an implicit break in every case. Sure, it's nice to save ink, but the pros of it don't outweigh the cons.
Dec 01 2003
The default, implicit, behavior should be the most common behavior needed by the programmer. For this reason, "in" parameters do not need explicitly specified as "in". break is much more common than fallthru, and would be even more so if case supported ranges or multiple values. Sean "Georg Wrede" <Georg_member pathlink.com> wrote in message news:bqf21n$81m$1 digitaldaemon.com...The rant about touch typing was (among other things) for the guys who wanted an implicit break in every case. Sure, it's nice to save ink, but the pros of it don't outweigh the cons.
Dec 01 2003
Yeah, I agree. I'd like to use smthng like: switch a case 1,3..8,15,99: //etc.... default: //etc.... end It is easier than the fallthrough approach.... In article <bqg1ki$1n9k$1 digitaldaemon.com>, Sean L. Palmer says...The default, implicit, behavior should be the most common behavior needed by the programmer. For this reason, "in" parameters do not need explicitly specified as "in". break is much more common than fallthru, and would be even more so if case supported ranges or multiple values. Sean "Georg Wrede" <Georg_member pathlink.com> wrote in message news:bqf21n$81m$1 digitaldaemon.com...The rant about touch typing was (among other things) for the guys who wanted an implicit break in every case. Sure, it's nice to save ink, but the pros of it don't outweigh the cons.
Dec 01 2003
In article <bqf21n$81m$1 digitaldaemon.com>, Georg Wrede wrote:If it were obligatory to write the default statement, then these latter folks would just learn that that is something that has to be there, and obviously the line would be 'default: break;'. When their programs don't work the way they expect, then they have a very hard time finding out why. And since the compiler couldn't warn or error about this, the only way is to figure out why it acts other than we wished.This reminds of the classic way Java novices learn to use exception specifications instead of the infamous "try ... catch { }" idiom. Step 1: "My program doesn't compile." "Wrap your functions in try statements and accompany them with empty catch statements." Step 2: "Now it compiles!" "Great! Did you try to run it?" Step 3: "Now it crashes..." "All right. Now let me tell you about exception specifications..." (It's funny 'cos it's true!) In an ideal language, the programmer should not be forced to write something "just because". Every line of code should mean something. "default: break;" does not say much, so maybe it would be best to just leave it unsaid? A single "return 0"; in the end of the function is not very informative either. C++ is overly verbose and tedious because it forces you to say "public" and "virtual" and "= 0" and "const" everywhere and demands that you maintain two copies of function and member function declarations (at worst three if you want insulation). And it forces you to say "break" all the time.The rant about touch typing was (among other things) for the guys who wanted an implicit break in every case. Sure, it's nice to save ink, but the pros of it don't outweigh the cons.Perhaps I'm reaching for the Dark Side by saying that the most common operation should be the default -- so that the programmer wouldn't have to type and read as much. In other word, I'm suggesting that the programmers should follow their natural tendency to be lazy. But on the other hand, shouldn't this principle be most satisfying to also the maintenance programmer, who would not be forced to search for the missing "break" in the switch statement (breaking is the most common operation, so why state the obvious, and the rare "fallthrough" or "goto case" would catch the reader's attention properly), and to spend time wondering if the return statement at the end of function was missing by purpose or by mistake? In short, requiring a "break" in a switch statement feels similar to requiring an empty "return" in the end of a function that does not in fact return anything. Of course, there are differing opinions as to what the most common operation in fact is. Some might even carry the opinion that in the switch statement, it's falling through -- obviously. Why else would C's switch statement fall through by default? Another feeling that comes with this is that in general, certain things should not happen silently. Such as throwing compiler-generated exceptions. If you want to make a function which throws an exception if the end of the function is reached, it would be in my opinion fair to force the programmer to write "assert(0)" or "throw ShouldNotBeHereException" or something similar before the end of the function. And if the programmer just happened to forget the return statement (or the exception), the compiler would immediately complain about it. -Antti
Dec 01 2003
Terse code is much easier to scan visually (think scanning a 1000-line program written by a novice vs. an equivalent 100-line program written by a guru) In wordy code, there are more places for bugs to hide. It is easy to maintain code that isn't there. It is hard to remove code once it has been added. IMHO, the shorter a piece of code is, the better, up to near the information limit. Simplify, simplify, simplify, until there is no more redundancy, fluff, or contorted logic remaining. Sean "Antti Sykäri" <jsykari gamma.hut.fi> wrote in message news:slrnbsn7ls.17n.jsykari pulu.hut.fi...In an ideal language, the programmer should not be forced to write something "just because". Every line of code should mean something. "default: break;" does not say much, so maybe it would be best to just leave it unsaid? A single "return 0"; in the end of the function is not very informative either. C++ is overly verbose and tedious because it forces you to say "public" and "virtual" and "= 0" and "const" everywhere and demands that you maintain two copies of function and member function declarations (at worst three if you want insulation). And it forces you to say "break" all the time. Perhaps I'm reaching for the Dark Side by saying that the most common operation should be the default -- so that the programmer wouldn't have to type and read as much. In other word, I'm suggesting that the programmers should follow their natural tendency to be lazy. But on the other hand, shouldn't this principle be most satisfying to also the maintenance programmer, who would not be forced to search for the missing "break" in the switch statement (breaking is the most common operation, so why state the obvious, and the rare "fallthrough" or "goto case" would catch the reader's attention properly), and to spend time wondering if the return statement at the end of function was missing by purpose or by mistake? In short, requiring a "break" in a switch statement feels similar to requiring an empty "return" in the end of a function that does not in fact return anything. Of course, there are differing opinions as to what the most common operation in fact is. Some might even carry the opinion that in the switch statement, it's falling through -- obviously. Why else would C's switch statement fall through by default? Another feeling that comes with this is that in general, certain things should not happen silently. Such as throwing compiler-generated exceptions. If you want to make a function which throws an exception if the end of the function is reached, it would be in my opinion fair to force the programmer to write "assert(0)" or "throw ShouldNotBeHereException" or something similar before the end of the function. And if the programmer just happened to forget the return statement (or the exception), the compiler would immediately complain about it. -Antti
Dec 01 2003
Walter wrote:Several C++ compilers do emit warnings for such. I find those warnings to be irritating rather than useful. For example, they will warn about: int foo() { while (1) { .... return ...; } } where it is *not possible* for the code to fall off the end, but the warning happens, and to get rid of it I have to put in a return statement that will never execute. I find being forced to add code that will never execute to be inelegant and potentially confusing. Hence my motivation for having D ensure that it never executes by raising an exception if it does, but that doesn't muck up the source code.There are a couple things I really don't like about that code anyway. For instance, it is usually bad practice to return from inside a loop--your language has to be very good at cleaning up its stack in these cases. Second, if you want to loop forever until something important happens, use while(true) instead of a number. Explicit booleans can make conditionals absolutely clear. Lastly, if you want to break a loop early, that is what the break keyward is for. I have seen several programs where there was a similar "loop" in the code, but instead of while(1) it was while(0). In essense the code would never run, but because it is not commented out, you might waste time looking in there. Anyhoo, I really don't like that snippet above for my own sense of code style purposes. It really isn't that clear. I have read in many places that it is much better to have the principle of one place of exit. Instead of having something like this: if (foo < bar) return -1; if (foo > bar) return 1; return 0; It would be better overall to have something like this: int ordinal = 0; if (foo < bar) ordinal--; if (foo > bar) ordinal++; return ordinal; There are a couple of reasons, first of which is that there is a clear exit point that will always be taken. Second of which we are being a little more semantically clear in that we are comparing the relative order of two objects, and returning a value where the sign is more important than the value. 0 means the objects are equal, negative means the second object should come before the first, and positive means the second object should come after the second. (This is adapted from how Comparators work in Java). While the first example is technically legal, the maintainer who comes along afterwords has to figure out what is going on. In this example it is relatively clear. However, I have had to maintain some methods where the return was buried within several statements inside the conditional, and not really clear where it was. By enforcing the principle of one place of exit, the snippet you provided would be better written as: int foo() { while(true) { ..... break; } return ...; } Since that is the true intention of the code.
Dec 01 2003
"Berin Loritsch" <bloritsch d-haven.org> wrote in message news:bqfiuc$vsf$1 digitaldaemon.com...Walter wrote:to beSeveral C++ compilers do emit warnings for such. I find those warningswarningirritating rather than useful. For example, they will warn about: int foo() { while (1) { .... return ...; } } where it is *not possible* for the code to fall off the end, but thewillhappens, and to get rid of it I have to put in a return statement thatto benever execute. I find being forced to add code that will never executeensureinelegant and potentially confusing. Hence my motivation for having Ddoesn'tthat it never executes by raising an exception if it does, but thatIt must be supported even if it's bad practice.muck up the source code.There are a couple things I really don't like about that code anyway. For instance, it is usually bad practice to return from inside a loop--your language has to be very good at cleaning up its stack in these cases.It isn't any extra work for the code generator <g>. The ugly problems are having returns inside try, finally or catch blocks.Second, if you want to loop forever until something important happens, use while(true)insteadof a number. Explicit booleans can make conditionals absolutely clear.Ironically, some other compilers I use complain about any use of while with a constant, whereas the blessed form of an infinite loop is for(;;). Every team seems to have a different view of the right way to do an infinite loop; I prefer while(1) because there's no way that some idjit #define'd true to be 0. (And yes, in the old C days, you would find such definitions of true.) And yes, in D true is a keyword and can't be mucked up that way, but old habits die hard <g>.Lastly, if you want to break a loop early, that is what the break keywardisfor. Anyhoo, I really don't like that snippet above for my own sense ofcode stylepurposes. It really isn't that clear.Perhaps not, but these snippets I post are the essence of some considerably longer piece of code. I remove all the irrelevant cruft to get a minimalist example. This sometimes results in a snippet few people would actually write, but what I'm doing is trying to illustrate something that should be handled correctly by the compiler, not advocating it as good style.I have read in many places that it is much better to have the principle ofoneplace of exit.You're right that there are many people who carefully follow the one exit rule. It is a perfectly reasonable style. But D isn't trying to enforce a particular style, it needs to be an easy migration path from C and C++ code, and such code uses returns in all kinds of weird places. If D forced a one exit rule on them, the potential users for D would shrink significantly.
Dec 09 2003
Walter, I just wanted to weigh in here. Your current design (implicit default throws and exception) is, IMHO, a Good Thing. Having the programmer add default: assert(0); is even better. Thus, I would argue (I know, you hate warnings, but hear me out) that a warning that explicitly states you are adding the implicit-throw-on-default is a good idea. It makes the C-porting task easier, and leads people toward better programming practice.
Nov 30 2003
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:bqd01e$cc0$1 digitaldaemon.com...Walter, I just wanted to weigh in here. Your current design (implicit default throws and exception) is, IMHO, a Good Thing.At least somebody likes it <g>.Having the programmer add default: assert(0); is even better.That's my normal practice in C/C++. Having that in there has saved me from countless bugs.
Dec 06 2003
Walter wrote:"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:bqd01e$cc0$1 digitaldaemon.com...I've been pondering this for a while, and I know that my view is going o be controversial... Walter is absolutely RIGHT... If you don't your switch recieves value that is nonsensical, you should have an error thrown (one that told you that is what happened would be nicer than assert(0) ). If you add a value to a enum and miss one of the switches out in maintainance, then it will be exposed when you run your test suite, to which you added a test for complience with the revised enum (you do do write tests for your new code don't you <g>). I cannot see a problem with Walter's choice of implementation that is not due to bad programming practices (even good programmers can have bad practices). I myself am a bad programmer with good practices, aided by D's clever features... Alix... -- Alix Pexton Webmaster - http://www.theDjournal.com Alix theDjournal.comWalter, I just wanted to weigh in here. Your current design (implicit default throws and exception) is, IMHO, a Good Thing.At least somebody likes it <g>.Having the programmer add default: assert(0); is even better.That's my normal practice in C/C++. Having that in there has saved me from countless bugs.
Dec 07 2003
I thinkWalter's way is better than not checking at all, but a few people on this NG (including me) think it would be even better if the compiler just complained at you that not all the cases were handled. If the compiler can tell that there are possible input values that aren't handled, it should require a default clause. I do not believe that enums that were typecasted from ints should be considered. If there is an error converting int to enum it should be exposed at the point of the cast, not worried about during a later switch. switch (value) { case 1: blah(); break; case 2: foo(); break; case 3: bar(); break; } Now what the programmer *probably* meant was that if you get 1,2, or 3, do those things, otherwise do nothing. But it's not explicit in the code. We would want it to mandatorily be explicit. Then if you want an assert, you put an assert, and if you do not, expecting C's rules to hold, you don't get burned by asserts thrown once your application ships, especially if the assert is thrown in a situation that otherwise would be perfectly gracefully handled (because you really *did* mean that if the case isn't matched, it should do nothing.) Anytime there is a runtime check, there is a bug waiting to happen. Make it so you don't need the check, and there is no possibility of a bug at all. That's better. Sean "Alix Pexton" <Alix thedjournal.com> wrote in message news:bqvchc$l7l$1 digitaldaemon.com...I've been pondering this for a while, and I know that my view is going o be controversial... Walter is absolutely RIGHT... If you don't your switch recieves value that is nonsensical, you should have an error thrown (one that told you that is what happened would be nicer than assert(0) ). If you add a value to a enum and miss one of the switches out in maintainance, then it will be exposed when you run your test suite, to which you added a test for complience with the revised enum (you do do write tests for your new code don't you <g>). I cannot see a problem with Walter's choice of implementation that is not due to bad programming practices (even good programmers can have bad practices). I myself am a bad programmer with good practices, aided by D's clever features... Alix...
Dec 07 2003
That's the most cogent opinion yet expressed. I heartily "hear, hear" it. Anything else is insanity. Thanks Sean "Sean L. Palmer" <palmer.sean verizon.net> wrote in message news:br040i$1mqc$1 digitaldaemon.com...I thinkWalter's way is better than not checking at all, but a few peopleonthis NG (including me) think it would be even better if the compiler just complained at you that not all the cases were handled. If the compilercantell that there are possible input values that aren't handled, it should require a default clause. I do not believe that enums that weretypecastedfrom ints should be considered. If there is an error converting int toenumit should be exposed at the point of the cast, not worried about during a later switch. switch (value) { case 1: blah(); break; case 2: foo(); break; case 3: bar(); break; } Now what the programmer *probably* meant was that if you get 1,2, or 3, do those things, otherwise do nothing. But it's not explicit in the code.Wewould want it to mandatorily be explicit. Then if you want an assert, you put an assert, and if you do not,expectingC's rules to hold, you don't get burned by asserts thrown once your application ships, especially if the assert is thrown in a situation that otherwise would be perfectly gracefully handled (because you really *did* mean that if the case isn't matched, it should do nothing.) Anytime there is a runtime check, there is a bug waiting to happen. Makeitso you don't need the check, and there is no possibility of a bug at all. That's better. Sean "Alix Pexton" <Alix thedjournal.com> wrote in message news:bqvchc$l7l$1 digitaldaemon.com...I've been pondering this for a while, and I know that my view is going o be controversial... Walter is absolutely RIGHT... If you don't your switch recieves value that is nonsensical, you should have an error thrown (one that told you that is what happened would be nicer than assert(0) ). If you add a value to a enum and miss one of the switches out in maintainance, then it will be exposed when you run your test suite, to which you added a test for complience with the revised enum (you do do write tests for your new code don't you <g>). I cannot see a problem with Walter's choice of implementation that is not due to bad programming practices (even good programmers can have bad practices). I myself am a bad programmer with good practices, aided by D's clever features... Alix...
Dec 07 2003
Sean L. Palmer wrote:Now what the programmer *probably* meant was that if you get 1,2, or 3, do those things, otherwise do nothing. But it's not explicit in the code. We would want it to mandatorily be explicit. Then if you want an assert, you put an assert, and if you do not, expecting C's rules to hold, you don't get burned by asserts thrown once your application ships, especially if the assert is thrown in a situation that otherwise would be perfectly gracefully handled (because you really *did* mean that if the case isn't matched, it should do nothing.) Anytime there is a runtime check, there is a bug waiting to happen. Make it so you don't need the check, and there is no possibility of a bug at all. That's better.I agree. Also, I would like to add one additonal point: What is the difference between a "switch" without a "default" and an "if" without an "else"? "If" and "switch" can both be used for the same thing, so why throw an exception when there is no "default", but not if the is not "else"? I believe the answer is personal coding style. It seems that Walter and a few others mostly use switch for things where they want to catch every possible condition. But it doesn't HAVE to be that way. Other programmers may want switch to behave simply like an "if-else if" chain without a final else. A good exmaple for this is a Windows WNDPROC procedure. In this you want to handle SOME of the messages in a special way, and pass others on to DefWindowProc. But you also quite often want to pass the handled messages to DefWindowProc as well. So such a procedure usually looks like this: LRESULT myWindowProc(....) { switch(message) { case WM_LBUTTONDOWN: doThis(); break; case WM....: doThat(); break; case WM...: doAnotherThing(); return 0; //don't call DefWindowProc break; } return CallWindowProc(DefWindowProc,...); } In my opinion. that's a perfectly valid way to use a switch. Throwing an exception by default would cause quite some bugs, I think. IMHO the best thing is to require the default clause, as was suggested multiple times. That way no one can be surprised by unexpected behaviour of the compiler. HaukeSean "Alix Pexton" <Alix thedjournal.com> wrote in message news:bqvchc$l7l$1 digitaldaemon.com...I've been pondering this for a while, and I know that my view is going o be controversial... Walter is absolutely RIGHT... If you don't your switch recieves value that is nonsensical, you should have an error thrown (one that told you that is what happened would be nicer than assert(0) ). If you add a value to a enum and miss one of the switches out in maintainance, then it will be exposed when you run your test suite, to which you added a test for complience with the revised enum (you do do write tests for your new code don't you <g>). I cannot see a problem with Walter's choice of implementation that is not due to bad programming practices (even good programmers can have bad practices). I myself am a bad programmer with good practices, aided by D's clever features... Alix...
Dec 08 2003
Good point. Especially since it is possible to switch on strings, but as long as default is required, that is no real problem (as you also point out). In my ddepcheck program, I use a switch to check the command line switches. A few of them aren't as easy as doing a case on them, so I first switch on the easy ones (having 'default: break;' at the end), then I continue with some ifs and stuff. I expect dmd 0.77 to flag a compile error when encountering switches without default. :) Lars Ivar Igesund "Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:br1di4$m1o$1 digitaldaemon.com...Sean L. Palmer wrote:doNow what the programmer *probably* meant was that if you get 1,2, or 3,Wethose things, otherwise do nothing. But it's not explicit in the code.expectingwould want it to mandatorily be explicit. Then if you want an assert, you put an assert, and if you do not,thatC's rules to hold, you don't get burned by asserts thrown once your application ships, especially if the assert is thrown in a situation*did*otherwise would be perfectly gracefully handled (because you reallyMake itmean that if the case isn't matched, it should do nothing.) Anytime there is a runtime check, there is a bug waiting to happen.all.so you don't need the check, and there is no possibility of a bug atThat's better.I agree. Also, I would like to add one additonal point: What is the difference between a "switch" without a "default" and an "if" without an "else"? "If" and "switch" can both be used for the same thing, so why throw an exception when there is no "default", but not if the is not "else"? I believe the answer is personal coding style. It seems that Walter and a few others mostly use switch for things where they want to catch every possible condition. But it doesn't HAVE to be that way. Other programmers may want switch to behave simply like an "if-else if" chain without a final else. A good exmaple for this is a Windows WNDPROC procedure. In this you want to handle SOME of the messages in a special way, and pass others on to DefWindowProc. But you also quite often want to pass the handled messages to DefWindowProc as well. So such a procedure usually looks like this: LRESULT myWindowProc(....) { switch(message) { case WM_LBUTTONDOWN: doThis(); break; case WM....: doThat(); break; case WM...: doAnotherThing(); return 0; //don't call DefWindowProc break; } return CallWindowProc(DefWindowProc,...); } In my opinion. that's a perfectly valid way to use a switch. Throwing an exception by default would cause quite some bugs, I think. IMHO the best thing is to require the default clause, as was suggested multiple times. That way no one can be surprised by unexpected behaviour of the compiler. HaukeSean "Alix Pexton" <Alix thedjournal.com> wrote in message news:bqvchc$l7l$1 digitaldaemon.com...I've been pondering this for a while, and I know that my view is going o be controversial... Walter is absolutely RIGHT... If you don't your switch recieves value that is nonsensical, you should have an error thrown (one that told you that is what happened would be nicer than assert(0) ). If you add a value to a enum and miss one of the switches out in maintainance, then it will be exposed when you run your test suite, to which you added a test for complience with the revised enum (you do do write tests for your new code don't you <g>). I cannot see a problem with Walter's choice of implementation that is not due to bad programming practices (even good programmers can have bad practices). I myself am a bad programmer with good practices, aided by D's clever features... Alix...
Dec 08 2003
In article <br1di4$m1o$1 digitaldaemon.com>, Hauke Duden says...What is the difference between a "switch" without a "default" and an "if" without an "else"? "If" and "switch" can both be used for the same thing, so why throw an exception when there is no "default", but not if the is not "else"?ah! ah! let's see Walter dodging this one ;) Ant
Dec 08 2003
Ant wrote:In article <br1di4$m1o$1 digitaldaemon.com>, Hauke Duden says...Here's one reason. ---------------- if (x == 2) ... else if (x == 5) ... //No else things run fine, therefore no assertion needed ---------------- switch (x) { case 2: ... //On no, forgot the break. But it's ok, because the compiler (might) tell me at runtime, when it falls through to default. case 5: .. //Forget the break here as well. -> if you do it once, you might do it twice. } I'd prefer compile time errors that enforce no-fall-though at compile-time (various structures have been offered) rather then -> maybe-crash-at-runtime when I least suspect it runtime-assertions.What is the difference between a "switch" without a "default" and an "if" without an "else"? "If" and "switch" can both be used for the same thing, so why throw an exception when there is no "default", but not if the is not "else"?ah! ah! let's see Walter dodging this one ;) Ant
Dec 08 2003
J Anderson wrote:You are trying to use one flaw to justify another! But since this "proves" that D should to require an explicit default AND should have an implicit break I'll let it pass ;). HaukeHere's one reason. switch (x) { case 2: ... //On no, forgot the break. But it's ok, because the compiler (might) tell me at runtime, when it falls through to default. case 5: .. //Forget the break here as well. -> if you do it once, you might do it twice. }What is the difference between a "switch" without a "default" and an "if" without an "else"? "If" and "switch" can both be used for the same thing, so why throw an exception when there is no "default", but not if the is not "else"?ah! ah! let's see Walter dodging this one ;) Ant
Dec 08 2003
Hauke Duden wrote:J Anderson wrote:For: switch (x) { case 2: ... //On no, forgot the break. But it's ok, because the compiler (might) tell me at runtime, when it falls through to default. case 5: .. //Forget the break here as well. -> if you do it once, you might do it twice. } What the coder meant to write was: switch (x) { case 2: ... //On no, forgot the break. But it's ok, because the compiler (might) tell me at runtime, when it falls through to default. break; case 5: .. //Forget the break here as well. -> if you do it once, you might do it twice. break; } If you had an explicit break coders may tend to write something like: switch (x) { case 2: ... //On no, forgot the break. But it's ok, because the compiler (might) tell me at runtime, when it falls through to default. case 5: .. //Forget the break here as well. -> if you do it once, you might do it twice. default: //On no, there's not even a runtime warning. } Which is why Walter (in C) puts in the assert, for the default. D does this automaticly (why write what the compiler already does?) At least you have a run-time warning if you forget to put in the breaks. So, it's not an argument for explicit default.You are trying to use one flaw to justify another! But since this "proves" that D should to require an explicit default AND should have an implicit break I'll let it pass ;). HaukeHere's one reason. switch (x) { case 2: ... //On no, forgot the break. But it's ok, because the compiler (might) tell me at runtime, when it falls through to default. case 5: .. //Forget the break here as well. -> if you do it once, you might do it twice. }What is the difference between a "switch" without a "default" and an "if" without an "else"? "If" and "switch" can both be used for the same thing, so why throw an exception when there is no "default", but not if the is not "else"?ah! ah! let's see Walter dodging this one ;) Ant
Dec 08 2003
J Anderson wrote:For: <switch without breaks> What the coder meant to write was: <switch with breaks> If you had an explicit break coders may tend to write something like: switch (x) { case 2: ... //On no, forgot the break. But it's ok, because the compiler (might) tell me at runtime, when it falls through to default. case 5: .. //Forget the break here as well. -> if you do it once, you might do it twice. default: //On no, there's not even a runtime warning. } Which is why Walter (in C) puts in the assert, for the default. D does this automaticly (why write what the compiler already does?) At least you have a run-time warning if you forget to put in the breaks. So, it's not an argument for explicit default.What I said was that D should have both a IMplicit break and an EXplicit default (actually, I'd prefer if a missing default had no effect at all - no exception and no error - but I'd settle for the explicit one. It's still much better than the runtime exception.). With implicit breaks your example could never happen, since the breaks would always be (implicitly) there. Apart from that, I think that arguing that the "default" exception can be used to catch missing breaks is a little too constructed. It'd only work if the missing break was the very last one. And even if it is you'd get a misleading error message. I.e. you'd think that you got an unexpected switch value, not that you got an expected one and your code was just missing a break. Hauke
Dec 08 2003
Oh, well then you'll love this: I recently came up with a different approach to if... As you may recall, I always put braces on all my ifs, fors, whiles, etc. It occurred to me that I could create a language (after all any old fool can do it -- hee hee) that has an if like this -- if expr { // then-part § // in case that didn't go right, that's the "section" mark // else-part } All three symbols are required and therefor you can't have an if without an else (although of course it may be empty). In article <br29ht$20j9$1 digitaldaemon.com>, J Anderson says...Ant wrote:In article <br1di4$m1o$1 digitaldaemon.com>, Hauke Duden says...Here's one reason. ---------------- if (x == 2) ... else if (x == 5) ... //No else things run fine, therefore no assertion needed ---------------- switch (x) { case 2: ... //On no, forgot the break. But it's ok, because the compiler (might) tell me at runtime, when it falls through to default. case 5: .. //Forget the break here as well. -> if you do it once, you might do it twice. } I'd prefer compile time errors that enforce no-fall-though at compile-time (various structures have been offered) rather then -> maybe-crash-at-runtime when I least suspect it runtime-assertions.What is the difference between a "switch" without a "default" and an "if" without an "else"? "If" and "switch" can both be used for the same thing, so why throw an exception when there is no "default", but not if the is not "else"?ah! ah! let's see Walter dodging this one ;) Ant
Dec 08 2003
"Sean L. Palmer" <palmer.sean verizon.net> wrote in message news:br040i$1mqc$1 digitaldaemon.com...I thinkWalter's way is better than not checking at all, but a few peopleonthis NG (including me) think it would be even better if the compiler just complained at you that not all the cases were handled.This is equivalent to requiring that an explicit default statement always be provided. There's no way the compiler can prove all cases were handled.If the compiler can tell that there are possible input values that aren't handled, it should require a default clause.There's just no way for the compiler to do this.I do not believe that enums that were typecasted from ints should be considered. If there is an error converting int toenumit should be exposed at the point of the cast, not worried about during a later switch.Casting ints to enums should not be an error. Consider, for example, gathering input from a data file and converting it to an enum. If the cast is made illegal, then the programmer will just do it another way, such as type painting or using an enum. Other values can also creep in from coding bugs elsewhere, pointer bugs, etc.switch (value) { case 1: blah(); break; case 2: foo(); break; case 3: bar(); break; } Now what the programmer *probably* meant was that if you get 1,2, or 3, do those things, otherwise do nothing. But it's not explicit in the code.Wewould want it to mandatorily be explicit.I view the above switch statement as explicitly saying "the only possible values for value are 1, 2 or 3. No other values are possible. Therefore, it is a program bug if there are any other values." This also means the D optimizer is allowed to take advantage of the knowledge after the end of the switch that value can only have the values 1, 2, or 3. If an explicit default is given, that means that other values are possible.Then if you want an assert, you put an assert, and if you do not,expectingC's rules to hold, you don't get burned by asserts thrown once your application ships, especially if the assert is thrown in a situation that otherwise would be perfectly gracefully handled (because you really *did* mean that if the case isn't matched, it should do nothing.)The throwing of the switch default exception is not causing a bug in the program. It is detecting a bug in a manner that is more reasonable than the random, erratic behavior caused by unanticipated input. DM compilers are loaded up with such runtime checking; I'm sure you're all familiar with the messages it produces! I'm sure you've also noticed that the compiler rarely crashes as a result of a bug, it usually semi-gracefully quits with an internal error message. I much prefer the latter to the former.Anytime there is a runtime check, there is a bug waiting to happen.I don't agree, since I think it's equivalent to saying that stripping all error checking code out of a program will improve its reliability. The whole idea of Design by Contract is to validate various assertions about the state of the program. Invalid states are supposed to cause the program to terminate gracefully. Unanticipated values in a switch statement certainly are an invalid state of the program, and checking for them is a (small) part of DbC.Make it so you don't need the check, and there is no possibility of a bug at all. That's better.I certainly agree with that. But I think that is not our point of disagreement - our disagreement is whether the runtime check should be put in by the programmer or by the compiler. If you explicitly insert default:assert(0); there's still a runtime check! I'll reiterate that there's no way that the compiler can prove that all cases are covered without a default statement. You have an excellent point that the semantics differ from C, where the implicitly generated default statement is default:break; rather than default:assert(0);. Interestingly, from a code generation perspective, you can save a bit of space and time by having no default case at all. This is possible in D (it is not possible in C) when compiled with runtime checking turned off.
Dec 08 2003
In article <br3s0u$19rs$1 digitaldaemon.com>, Walter says...Yes I would view the switch statement the same way. There are three ways of looking at this. 1) No 'default' means that all other values are an error. The programmer should explicitly state that other values are not an error condition by putting default: break; 2) No 'default' means that other values are acceptable. The programmer must explicitly state that other values are an error condition by putting default: assert(0); 3) 'No default' is a compiler error. The programmer must explicitly state how other values are handled. As far as explicitly stating the programmers intention all three work equally well when combined with firm documentation of the default behavior of the switch statement. All that option 3 really does is save the programmer from an error of omission. In other words the programmer really intended the opposite behavior from what the default is but forgot to include the 'default' statement. How is this any different that any other error of omission? Are you more likely to forget a 'default' in a 'switch' than a 'else' on a 'if'? Now as for choosing between options 1 and 2. It makes sense to me that a switch lists the values that are handled, not the values that are not handled. So if a value is not in the list it is an error. 'default' means I handle every other value not explicitly listed. As for throwing a runtime error for the implicit default case it is really very similar to the runtime error for an array index out of bounds. I don't have any problem with this behavior. So I'm voting for Walter's current implementation.switch (value) { case 1: blah(); break; case 2: foo(); break; case 3: bar(); break; } Now what the programmer *probably* meant was that if you get 1,2, or 3, do those things, otherwise do nothing. But it's not explicit in the code.Wewould want it to mandatorily be explicit.I view the above switch statement as explicitly saying "the only possible values for value are 1, 2 or 3. No other values are possible. Therefore, it is a program bug if there are any other values." This also means the D optimizer is allowed to take advantage of the knowledge after the end of the switch that value can only have the values 1, 2, or 3. If an explicit default is given, that means that other values are possible.
Dec 09 2003
Patrick Down wrote:There are three ways of looking at this. 1) No 'default' means that all other values are an error. The programmer should explicitly state that other values are not an error condition by putting default: break; 2) No 'default' means that other values are acceptable. The programmer must explicitly state that other values are an error condition by putting default: assert(0); 3) 'No default' is a compiler error. The programmer must explicitly state how other values are handled. As far as explicitly stating the programmers intention all three work equally well when combined with firm documentation of the default behavior of the switch statement. All that option 3 really does is save the programmer from an error of omission. In other words the programmer really intended the opposite behavior from what the default is but forgot to include the 'default' statement. How is this any different that any other error of omission? Are you more likely to forget a 'default' in a 'switch' than a 'else' on a 'if'?There is one important difference: it works differently in all other major languages. I programmed in C, C++ and JAVA for many years and I fear that I WILL forget to put that default in there. D's syntax is so similar in many respects and the construct even has the same name! So this is an accident waiting to happen. But the worst thing about this is that when that accident happens I might not know it until it is too late (i.e. when the application is shipped and some user has done something that causes the default case to trigger). That's why I prefer the explicit default. No matter what you think is intuitive (and we have seen that this IS different from person to person), the compiler will warn you right when you made your mistake. Then you just type an additional line and there's no harm done. Compare that to the case where I have to find the bug after a user has told me "Your software thingy crashed! I didn't do anything!". Hauke
Dec 09 2003
Hauke Duden wrote:Patrick Down wrote:Do you send out distributions that are compiled in debug mode? In release mode an assert won't occur. If you have an explicit default, you still don't know if you've missed a case value. All you know is that you've handled all cases, which is a different thing.There are three ways of looking at this. 1) No 'default' means that all other values are an error. The programmer should explicitly state that other values are not an error condition by putting default: break; 2) No 'default' means that other values are acceptable. The programmer must explicitly state that other values are an error condition by putting default: assert(0); 3) 'No default' is a compiler error. The programmer must explicitly state how other values are handled. As far as explicitly stating the programmers intention all three work equally well when combined with firm documentation of the default behavior of the switch statement. All that option 3 really does is save the programmer from an error of omission. In other words the programmer really intended the opposite behavior from what the default is but forgot to include the 'default' statement. How is this any different that any other error of omission? Are you more likely to forget a 'default' in a 'switch' than a 'else' on a 'if'?There is one important difference: it works differently in all other major languages. I programmed in C, C++ and JAVA for many years and I fear that I WILL forget to put that default in there. D's syntax is so similar in many respects and the construct even has the same name! So this is an accident waiting to happen. But the worst thing about this is that when that accident happens I might not know it until it is too late (i.e. when the application is shipped and some user has done something that causes the default case to trigger). That's why I prefer the explicit default. No matter what you think is intuitive (and we have seen that this IS different from person to person), the compiler will warn you right when you made your mistake. Then you just type an additional line and there's no harm done. Compare that to the case where I have to find the bug after a user has told me "Your software thingy crashed! I didn't do anything!". Hauke
Dec 09 2003
J Anderson wrote:Do you send out distributions that are compiled in debug mode? In release mode an assert won't occur.Problem is, D doesn't do an assert, it throws an exception (SwitchException, if I recall it correctly). Walter just wrote default;assert(0); "metaphorically" in this discussion (he said so somewhere himself). Hauke
Dec 10 2003
Hauke Duden <H.NS.Duden gmx.net> wrote in news:br6oio$2pf2$1 digitaldaemon.com:J Anderson wrote:Actaully these execptions are compliled out in the release version, just like the array bounds checking. ( Walter correct me if I'm wrong. )Do you send out distributions that are compiled in debug mode? In release mode an assert won't occur.Problem is, D doesn't do an assert, it throws an exception (SwitchException, if I recall it correctly). Walter just wrote default;assert(0); "metaphorically" in this discussion (he said so somewhere himself).
Dec 10 2003
I still don't think that the compiler should spend its time checking for poor or perhaps-mistake-ridden code. That should be a job for some other utility. The compiler should merely compile what its given, only confirming that the code is legal. It seems hypocritical to me that you want to fill up the compiler with all sorts of bloat and then complain that builds take too long. <And, yes, I'm talking about your if (x = y ) being illegal bit of nonsense.> A file doesn't need to be checked for rookie mistakes every time it's compiled, only when it's changed. If we write and check a file and then put it into a code library, why check it again when it's pulled out for inclusion in a new project? If D is to be for beginners, then OK, put training wheels on it. But if it's to be for experienced power programmers who write expressively and perhaps obfuscatedly (?), then trust us to know what we're doing! Or maybe add an /expert or /fast switch to the command line, or have /release not check such things? In article <Xns944D595474DC9patcodemooncom 63.105.9.61>, Patrick Down says...Hauke Duden <H.NS.Duden gmx.net> wrote in news:br6oio$2pf2$1 digitaldaemon.com:J Anderson wrote:Actaully these execptions are compliled out in the release version, just like the array bounds checking. ( Walter correct me if I'm wrong. )Do you send out distributions that are compiled in debug mode? In release mode an assert won't occur.Problem is, D doesn't do an assert, it throws an exception (SwitchException, if I recall it correctly). Walter just wrote default;assert(0); "metaphorically" in this discussion (he said so somewhere himself).
Dec 10 2003
We're very far from experiencing any speed problems at compilation. These checks simply don't need any significant time. Juan C. wrote:A file doesn't need to be checked for rookie mistakes every time it's compiled, only when it's changed. If we write and check a file and then put it into a code library, why check it again when it's pulled out for inclusion in a new project?When you compile the library, you need to place the source into src. And then incude the binary when linking. However, the source is generally unused when compiling other modules, only declarations are extracted, the code itself is added by the linker. For efficiency reasons, source code can be taken for inlining from src, but nontheless no warnings about the code should be output. BTW, you can compile a library from source, then install "headers" stripped of function bodies into src. This also works.If D is to be for beginners, then OK, put training wheels on it. But if it's to be for experienced power programmers who write expressively and perhaps obfuscatedly (?), then trust us to know what we're doing!D should definately be good for beginners. Professionals have C++: a language which is somewhat complicated but fascinating and wonderful as you start to get it. But one which calls for trouble if you just begin to learn it. Obfuscated code is to be more or less forbidden in D. Look at Walter's code, it's very clean. It looks more or less like code a Delphi programmer would write. :)Or maybe add an /expert or /fast switch to the command line, or have /release not check such things?You know that Walter is strongly against such things. Compiler switches should not change the sematics of the language, else we shall have portability problems among build environments. Anyway, who cares how long release compiles take? And by the way, the back-end takes itself quite some time when you want to compile with optimisations. -eye PS. Walter, wouldn't you call this if(x=y) check a "nag"? No, i'm not against it, but i was questioning consistency.
Dec 10 2003
Patrick Down wrote:Hauke Duden <H.NS.Duden gmx.net> wrote in news:br6oio$2pf2$1 digitaldaemon.com:That is what I ment.J Anderson wrote:Actaully these execptions are compliled out in the release version, just like the array bounds checking. ( Walter correct me if I'm wrong. )Do you send out distributions that are compiled in debug mode? In release mode an assert won't occur.Problem is, D doesn't do an assert, it throws an exception (SwitchException, if I recall it correctly). Walter just wrote default;assert(0); "metaphorically" in this discussion (he said so somewhere himself).
Dec 10 2003
"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bq2vi2$tqd$1 digitaldaemon.com...ifWe should have also an option to specify that each possible values must have a label for case when all cases must be handled. This would typically be usefull for enumerations where we might want to ensure that all values appears.A good idea, but this is already addressed in D where the default case,I agree. Lars Ivar Igesundnot specified, is to throw an exception.Wow! That's a *really*, *REALLY* bad idea.
Nov 26 2003
"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bq2vi2$tqd$1 digitaldaemon.com...ifA good idea, but this is already addressed in D where the default case,thenot specified, is to throw an exception.Wow! That's a *really*, *REALLY* bad idea. If one is porting some code which very rarely uses the default case - it's largely irrelevant whether that's benign or a bug - it may easily escapetest cases, and "sometime later", in production code, an exception will be thrown which has never been anticipated and therefore never been handled.If it's never been anticipated and never been handled, then it's a program bug. What the exception does is give a controlled failure of the program, rather than an unpredictable erratic behavior.This is about the very best/worst example I could possibly think of in the debate between compile-time and runtime error-handling. Rather thancausingme 30 seconds in development time, I am up for an unknown, and potentially huge, cost sometime after deployment. Is D really wanting to be a serious systems language?A robust system programming language *should* give an exception on an unanticipated, unhandled situation.
Nov 27 2003
case,A good idea, but this is already addressed in D where the defaultifit'snot specified, is to throw an exception.Wow! That's a *really*, *REALLY* bad idea. If one is porting some code which very rarely uses the default case -belargely irrelevant whether that's benign or a bug - it may easily escapethetest cases, and "sometime later", in production code, an exception willhandled.thrown which has never been anticipated and therefore never beenIf it's never been anticipated and never been handled, then it's a program bug. What the exception does is give a controlled failure of the program, rather than an unpredictable erratic behavior.This is just plain wrong. What you're saying is that D must reflect the bugs inherent in code that is ported in from other languages, so kind of admitting defeat, or that D should facilitate, nay encourage, the shit practises of people who have abused weaknesses in other languages.theThis is about the very best/worst example I could possibly think of inpotentiallydebate between compile-time and runtime error-handling. Rather thancausingme 30 seconds in development time, I am up for an unknown, andserioushuge, cost sometime after deployment. Is D really wanting to be aA robust system programming language should favour compile time error fixes than runtime ones. Since exceptions are a questionable error-handling mechanism at best (flame me now, you "modern" programmers!!!) you're locking people into having to care about arbitrary bugs, in arbitrary modules (that may be other people's libraries), when this could all be obviated by the compiler doing marginally better than those for languages D that purports to be an improvement over. Sorry, but, much as I love and respect the very air that you breath Walter ;), this is just utter folly. Bertie Bettermentsystems language?A robust system programming language *should* give an exception on an unanticipated, unhandled situation.
Nov 27 2003
Have to agree here, I rareley ( never ? ) use exceptions , and dont like them being thrown without my knoweldge / consent. C "Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bq5m7f$2023$1 digitaldaemon.com...escapecase,A good idea, but this is already addressed in D where the defaultifit'snot specified, is to throw an exception.Wow! That's a *really*, *REALLY* bad idea. If one is porting some code which very rarely uses the default case -largely irrelevant whether that's benign or a bug - it may easilywillthetest cases, and "sometime later", in production code, an exceptionbeprogramhandled.thrown which has never been anticipated and therefore never beenIf it's never been anticipated and never been handled, then it's aprogram,bug. What the exception does is give a controlled failure of thebugsrather than an unpredictable erratic behavior.This is just plain wrong. What you're saying is that D must reflect theinherent in code that is ported in from other languages, so kind of admitting defeat, or that D should facilitate, nay encourage, the shit practises of people who have abused weaknesses in other languages.fixestheThis is about the very best/worst example I could possibly think of inpotentiallydebate between compile-time and runtime error-handling. Rather thancausingme 30 seconds in development time, I am up for an unknown, andserioushuge, cost sometime after deployment. Is D really wanting to be aA robust system programming language should favour compile time errorsystems language?A robust system programming language *should* give an exception on an unanticipated, unhandled situation.than runtime ones. Since exceptions are a questionable error-handling mechanism at best(flameme now, you "modern" programmers!!!) you're locking people into having to care about arbitrary bugs, in arbitrary modules (that may be otherpeople'slibraries), when this could all be obviated by the compiler doingmarginallybetter than those for languages D that purports to be an improvement over. Sorry, but, much as I love and respect the very air that you breath Walter ;), this is just utter folly. Bertie Betterment
Nov 27 2003
Have to agree here, I rareley ( never ? ) use exceptions , and dont like them being thrown without my knoweldge / consent.Exactamundo, my friend. Exceptions are great for somethings, including actual serious/fatal errors, or when doing stuff like deep-level parsing. Where they are absolutely not appropriate - and I can't believe this is even a discusson - is a runtime report of a code-time mistake!!
Nov 27 2003
"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bq65gu$2n8o$1 digitaldaemon.com...errors,Have to agree here, I rareley ( never ? ) use exceptions , and dont like them being thrown without my knoweldge / consent.Exactamundo, my friend. Exceptions are great for somethings, including actual serious/fatalor when doing stuff like deep-level parsing. Where they are absolutely not appropriate - and I can't believe this isevena discusson - is a runtime report of a code-time mistake!!There's no way to detect the error at compile time. What it's for is when one has: switch (x) { case 1: ... case 2: ... case 3: ... } and then one day x has the value 4. In C, there's an implicit default:break; inserted when no default is explicitly supplied. But in my experience coding, debugging my own mistakes, and fixing other peoples' code, the implicit default break is almost always the WRONG thing to happen, and then something unexpected happens as a result (i.e. crash, data corruption, etc.). When I see C code like that, and can ask the author, the intention is that x will always be 1, 2 or 3 and NEVER anything else. That's why he wrote the switch that way. That's ok, but then the maintenance programmer adds a feature where x is 4, updates all the switch statements accordingly, but inevitably misses one in the 100,000 line program he's revising. Even if the original coder INTENDED to make use of the implicit default:break;, it has that distinct odor of a bug, and so I flag it in code reviews. And in my experience, it was never intended. For years, I've advocated 'defensive programming' in C by making it explicit that the default case can never happen with: switch (x) { case 1: ... case 2: ... case 3: ... default: assert(0); } This is the normal practice in my own code. There are 3 situations to deal with, the above one, and: switch (x) { case 1: ... case 2: ... case 3: ... default: break; } and: switch (x) { case 1: ... case 2: ... case 3: ... default: do something break; } What D does is make it easy to ensure that all the bases are covered by with a random crash from forgetting to deal with a case. The compiler cannot do this at compile time because it has no way of determining all possible values x can take. In that way, it's similar to run time array bounds checking. The only other way of doing this with a hope of robustness is to *require* an explicitly written default statement for every switch. This would certainly be a valid language strategy, but I don't really want to be nagged by the compiler to insert a default:assert(0); when I know darn well that x can never be 4 <g>.
Nov 27 2003
"Walter" <walter digitalmars.com> wrote in message news:bq6hkq$79q$1 digitaldaemon.com..."Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bq65gu$2n8o$1 digitaldaemon.com...likeHave to agree here, I rareley ( never ? ) use exceptions , and dontdefault:break;errors,them being thrown without my knoweldge / consent.Exactamundo, my friend. Exceptions are great for somethings, including actual serious/fatalor when doing stuff like deep-level parsing. Where they are absolutely not appropriate - and I can't believe this isevena discusson - is a runtime report of a code-time mistake!!There's no way to detect the error at compile time. What it's for is when one has: switch (x) { case 1: ... case 2: ... case 3: ... } and then one day x has the value 4. In C, there's an implicitinserted when no default is explicitly supplied. But in my experience coding, debugging my own mistakes, and fixing other peoples' code, the implicit default break is almost always the WRONG thing to happen, andthensomething unexpected happens as a result (i.e. crash, data corruption, etc.). When I see C code like that, and can ask the author, the intentionisthat x will always be 1, 2 or 3 and NEVER anything else. That's why hewrotethe switch that way. That's ok, but then the maintenance programmer adds a feature where x is 4, updates all the switch statements accordingly, but inevitably misses one in the 100,000 line program he's revising. Even iftheoriginal coder INTENDED to make use of the implicit default:break;, it has that distinct odor of a bug, and so I flag it in code reviews. And in my experience, it was never intended. For years, I've advocated 'defensive programming' in C by making itexplicitthat the default case can never happen with: switch (x) { case 1: ... case 2: ... case 3: ... default: assert(0); } This is the normal practice in my own code. There are 3 situations to deal with, the above one, and: switch (x) { case 1: ... case 2: ... case 3: ... default: break; } and: switch (x) { case 1: ... case 2: ... case 3: ... default: do something break; } What D does is make it easy to ensure that all the bases are covered by with a random crash from forgetting to deal with a case. The compilercannotdo this at compile time because it has no way of determining all possible values x can take. In that way, it's similar to run time array bounds checking. The only other way of doing this with a hope of robustness is to *require* an explicitly written default statement for every switch. This would certainly be a valid language strategy, but I don't really want tobenagged by the compiler to insert a default:assert(0); when I know darnwellthat x can never be 4 <g>.It's smacking me between the eyes that requiring the default is the sensible strategy. Original authoring costs are cheap; maintenance costs are expensive. You're just contradicting the bulk of this erudite argument by your knowingly weak convenience. Walter, if I can lose my bad habit of using leading underscores, I think you can endure this egregious constraint for the greater D good, no? :-)
Nov 27 2003
In article <bq6kl9$bd6$1 digitaldaemon.com>, Matthew Wilson says..."Walter" <walter digitalmars.com> wrote in message news:bq6hkq$79q$1 digitaldaemon.com...[...]I also support requiring default. The laziness is your biggest enemy, so type those 8 keys on the keyboard and that's all. But I know I'm almost alone here: people want to save typing, not to produce robust code. BTW, what about user defined enum? Can the compiler know whether all enum constants are used inside a switch, and signal to the programmer when some are missing and there is not a default? CiaoThe only other way of doing this with a hope of robustness is to *require* an explicitly written default statement for every switch. This would certainly be a valid language strategy, but I don't really want tobenagged by the compiler to insert a default:assert(0); when I know darnwellthat x can never be 4 <g>.It's smacking me between the eyes that requiring the default is the sensible strategy. Original authoring costs are cheap; maintenance costs are expensive. You're just contradicting the bulk of this erudite argument by your knowingly weak convenience.
Nov 28 2003
"Roberto Mariottini" <Roberto_member pathlink.com> wrote in message news:bq7gm2$1nqo$1 digitaldaemon.com...BTW, what about user defined enum? Can the compiler know whether all enum constants are used inside a switch, and signal to the programmer when somearemissing and there is not a default?Yes, but it would be presumptious for the compiler to assume that all values of an enum are possible.
Nov 28 2003
enumBTW, what about user defined enum? Can the compiler know whether allsomeconstants are used inside a switch, and signal to the programmer whenarevaluesmissing and there is not a default?Yes, but it would be presumptious for the compiler to assume that allof an enum are possible.Only if the default is there. Without the default, it would be appropriate. But wait! This is another reason to have the default ...
Nov 28 2003
ThisThe only other way of doing this with a hope of robustness is to *require* an explicitly written default statement for every switch.towould certainly be a valid language strategy, but I don't really wantsensiblebenagged by the compiler to insert a default:assert(0); when I know darnwellthat x can never be 4 <g>.It's smacking me between the eyes that requiring the default is thealonestrategy. Original authoring costs are cheap; maintenance costs are expensive. You're just contradicting the bulk of this erudite argument by your knowingly weak convenience.I also support requiring default. The laziness is your biggest enemy, so type those 8 keys on the keyboard and that's all. But I know I'm almosthere: people want to save typing, not to produce robust code.Well said. Alas, what you say seems to be true a lot of the time. Even with big W ... :(
Nov 28 2003
"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bq82ts$2jce$1 digitaldaemon.com...almostI also support requiring default. The laziness is your biggest enemy, so type those 8 keys on the keyboard and that's all. But I know I'maloneWhy is providing a runtime check that all the bases were covered make a program less robust? What really is the essential difference between requiring that the programmer explicitly code a default, and requiring him to explicitly check array bounds: if (0 <= i && i < array.length) j = array[i]; ?here: people want to save typing, not to produce robust code.Well said. Alas, what you say seems to be true a lot of the time. Even with big W ... :(
Nov 28 2003
"Walter" <walter digitalmars.com> wrote in message news:bq8adb$2u45$2 digitaldaemon.com..."Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bq82ts$2jce$1 digitaldaemon.com......almostI also support requiring default. The laziness is your biggest enemy, so type those 8 keys on the keyboard and that's all. But I know I'malonehere: people want to save typing, not to produce robust code.Well said. Alas, what you say seems to be true a lot of the time. Even with big WAnything that pushes out error-detection from (where it is achievable, of course) compile-time to runtime loses robustness. Isn't that axiomatic? If that's not the case, then why don't we all program in Python all the time? It'd be a damn sight easier.:(Why is providing a runtime check that all the bases were covered make a program less robust?What really is the essential difference between requiring that the programmer explicitly code a default, and requiring him to explicitly check array bounds: if (0 <= i && i < array.length) j = array[i]; ?This is not a valid analogy. Your example is the difference between checking values yourself, or having them checked at runtime. With the switch/default, it is the case of having the options checked at compile time (by requiring all members of an enum to be present), or explicitly telling the compiler that you are aware of/don't care about the default case (with missing enums, or with other types) vs not being "complete" in the code and letting the runtime handle it. They are quite different things.
Nov 28 2003
"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bq8cg7$30ro$1 digitaldaemon.com...It's not achievable at compile time, regardless of whether the default is inserted by the compiler or the programmer.Why is providing a runtime check that all the bases were covered make a program less robust?Anything that pushes out error-detection from (where it is achievable, of course) compile-time to runtime loses robustness. Isn't that axiomatic?himWhat really is the essential difference between requiring that the programmer explicitly code a default, and requiringcheckingto explicitly check array bounds: if (0 <= i && i < array.length) j = array[i]; ?This is not a valid analogy. Your example is the difference betweenvalues yourself, or having them checked at runtime. With theswitch/default,it is the case of having the options checked at compile time (by requiring all members of an enum to be present), or explicitly telling the compiler that you are aware of/don't care about the default case (with missingenums,or with other types) vs not being "complete" in the code and letting the runtime handle it. They are quite different things.Yes, but putting a 'default:assert(0);' in is a runtime check, regardless of whether it is coded explicitly or implicitly. Therefore, it is just like an array bounds check.
Dec 02 2003
"Walter" <walter digitalmars.com> wrote in message news:bqitol$2va4$1 digitaldaemon.com..."Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bq8cg7$30ro$1 digitaldaemon.com...aWhy is providing a runtime check that all the bases were covered makeofprogram less robust?Anything that pushes out error-detection from (where it is achievable,Why not?course) compile-time to runtime loses robustness. Isn't that axiomatic?It's not achievable at compile time, regardless of whether the default is inserted by the compiler or the programmer.
Dec 02 2003
"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bqjqtl$18hg$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:bqitol$2va4$1 digitaldaemon.com...make"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bq8cg7$30ro$1 digitaldaemon.com...Why is providing a runtime check that all the bases were coveredaaxiomatic?ofprogram less robust?Anything that pushes out error-detection from (where it is achievable,course) compile-time to runtime loses robustness. Isn't thatisIt's not achievable at compile time, regardless of whether the defaultCasting, unions, pointers, reading data from files, inline assembler, external functions, buffer overflows overwriting the stack with a virus(!), etc. All kinds of ways to have random bit patterns in an otherwise constrained repository for a type. Just the kinds of problems DbC should help catch <g>.inserted by the compiler or the programmer.Why not?
Dec 08 2003
"Walter" <walter digitalmars.com> wrote in message news:br3s0v$19rs$2 digitaldaemon.com...(..)Casting, unions, pointers, reading data from files, inline assembler, external functions, buffer overflows overwriting the stack with avirus(!),etc. All kinds of ways to have random bit patterns in an otherwise constrained repository for a type. Just the kinds of problems DbC should help catch <g>.I though this will throw an IllegalCastException or something like that but it doesn't: enum SomeEnum {cero, uno, dos, tres}; void main() { SomeEnum se = cast(SomeEnum)10; printf("%d\n", se); } Shouldn't the cast line had a runtime check? Just asking.
Dec 09 2003
"Julio César Carrascal Urquijo" <adnoctum phreaker.net> wrote in message news:br72i4$9f2$1 digitaldaemon.com...Shouldn't the cast line had a runtime check? Just asking.I could argue it both ways <g>.
Dec 18 2003
Walter <walter digitalmars.com> escribió en el mensaje de noticias brtenf$1uqp$1 digitaldaemon.com..."Julio César Carrascal Urquijo" <adnoctum phreaker.net> wrote in message news:br72i4$9f2$1 digitaldaemon.com...At least in debug builds, please! (Just like array bounds checking)Shouldn't the cast line had a runtime check? Just asking.I could argue it both ways <g>.
Dec 18 2003
"Julio César Carrascal Urquijo" <adnoctum phreaker.net> wrote in message news:brtn8a$2blv$1 digitaldaemon.com...Walter <walter digitalmars.com> escribió en el mensaje de noticias brtenf$1uqp$1 digitaldaemon.com...It's a good idea, but I have to redo the template stuff first."Julio César Carrascal Urquijo" <adnoctum phreaker.net> wrote in message news:br72i4$9f2$1 digitaldaemon.com...At least in debug builds, please! (Just like array bounds checking)Shouldn't the cast line had a runtime check? Just asking.I could argue it both ways <g>.
Dec 19 2003
Shall we reopen the discussion, or do you already know what you are going to do? Sean "Walter" <walter digitalmars.com> wrote in message news:brv8kk$1ldt$1 digitaldaemon.com...It's a good idea, but I have to redo the template stuff first.
Dec 19 2003
I think I know what to do. "Sean L. Palmer" <palmer.sean verizon.net> wrote in message news:brvl0p$28qn$1 digitaldaemon.com...Shall we reopen the discussion, or do you already know what you are goingtodo? Sean "Walter" <walter digitalmars.com> wrote in message news:brv8kk$1ldt$1 digitaldaemon.com...It's a good idea, but I have to redo the template stuff first.
Dec 19 2003
Walter <walter digitalmars.com> escribió en el mensaje de noticias brv8kk$1ldt$1 digitaldaemon.com... (...)It's a good idea, but I have to redo the template stuff first.Ok, thanks!
Dec 19 2003
Roberto Mariottini wrote:I also support requiring default. The laziness is your biggest enemy, so type those 8 keys on the keyboard and that's all. But I know I'm almost alone here: people want to save typing, not to produce robust code.Requiring default will bring us to people typing "default: break;" instead of "default: assert(0)" just exactly for the reason you stated!BTW, what about user defined enum? Can the compiler know whether all enum constants are used inside a switch, and signal to the programmer when some are missing and there is not a default?Cool idea! -eye
Nov 29 2003
Ilya Minkov wrote:Roberto Mariottini wrote:For some people, that is exactly what they want. You do need to walk a balance between *encouraging* good coding practice, and *requiring* it.I also support requiring default. The laziness is your biggest enemy, so type those 8 keys on the keyboard and that's all. But I know I'm almost alone here: people want to save typing, not to produce robust code.Requiring default will bring us to people typing "default: break;" instead of "default: assert(0)" just exactly for the reason you stated!
Dec 01 2003
"Ilya Minkov" <minkov cs.tum.edu> wrote in message news:bqaci5$2rl3$2 digitaldaemon.com...Requiring default will bring us to people typing "default: break;" instead of "default: assert(0)" just exactly for the reason you stated!A similar problem has happened with Java where it required you to list the possible exceptions generated by each function. Even expert programmers who publicly excoriated the practice would pepper their own code with generic catches just to shut up the compiler. The end result was that a rule that was supposed to increase robustness, actually wound up making things worse. Philosophically, I don't think a language is robust because it requires programmers to code in a certain way. I think it's robust if it allows programmers to program the way they want to, making robust programming practices easier to use than non-robust ones. For example, although D allows you to use pointers as you would in C, D provides better semantic alternatives (like out parameters) that are more robust, and easier to use than the pointer equivalents. It's a win-win. One can counter this by saying "why do static type checking at all, then? Why not do it at runtime?" It's an excellent point, and the answer is that it's just too expensive to do at runtime. Languages that rely on runtime type checking tend to run very slowly compared with statically typed languages. As always, everything is a compromise in programming, and so we have static type checking in D.
Dec 02 2003
Walter wrote:One can counter this by saying "why do static type checking at all, then? Why not do it at runtime?" It's an excellent point, and the answer is that it's just too expensive to do at runtime. Languages that rely on runtime type checking tend to run very slowly compared with statically typed languages. As always, everything is a compromise in programming, and so we have static type checking in D.You'd prefer runtime type checking to compile time type checking? Urrrgh! I think we are very different types of programmers... I prefer the compiler to tell me about as many bugs as possible while I can still do something about it (at compile time). If all the checks happen at runtime, chances are that some of these bugs will not be discovered until it's too late - i.e. when the program is shipped and a customer has run the program in a way that triggered some condition that was not tested. Hauke
Dec 02 2003
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:bqj2ca$4lq$1 digitaldaemon.com...Walter wrote:then?One can counter this by saying "why do static type checking at all,thatWhy not do it at runtime?" It's an excellent point, and the answer isweit's just too expensive to do at runtime. Languages that rely on runtime type checking tend to run very slowly compared with statically typed languages. As always, everything is a compromise in programming, and soNo, that's not what I meant. Certainly, the earlier errors can be detected, the better, and compile time is the earliest. The compiler should do as much as it can, and runtime checks inserted to cover what it cannot.have static type checking in D.You'd prefer runtime type checking to compile time type checking? Urrrgh! I think we are very different types of programmers...I prefer the compiler to tell me about as many bugs as possible while I can still do something about it (at compile time).Yes, you are correct.If all the checks happen at runtime, chances are that some of these bugs will not be discovered until it's too late - i.e. when the program is shipped and a customer has run the program in a way that triggered some condition that was not tested.You're right. But I'd also prefer a runtime that generated an exception on an untested unanticipated condition, rather than fall through to some essentially random default behavior, which is what happens with C's implicit switch default behavior. It's very, very important that programs fail in a controlled manner when they encounter unanticipated conditions.
Dec 02 2003
"Walter" <walter digitalmars.com> wrote in message news:bqjanc$gfp$1 digitaldaemon.com..."Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:bqj2ca$4lq$1 digitaldaemon.com...runtimeWalter wrote:then?One can counter this by saying "why do static type checking at all,thatWhy not do it at runtime?" It's an excellent point, and the answer isit's just too expensive to do at runtime. Languages that rely onsotype checking tend to run very slowly compared with statically typed languages. As always, everything is a compromise in programming, andwedetected,No, that's not what I meant. Certainly, the earlier errors can behave static type checking in D.You'd prefer runtime type checking to compile time type checking? Urrrgh! I think we are very different types of programmers...the better, and compile time is the earliest. The compiler should do asmuchas it can, and runtime checks inserted to cover what it cannot.implicitI prefer the compiler to tell me about as many bugs as possible while I can still do something about it (at compile time).Yes, you are correct.If all the checks happen at runtime, chances are that some of these bugs will not be discovered until it's too late - i.e. when the program is shipped and a customer has run the program in a way that triggered some condition that was not tested.You're right. But I'd also prefer a runtime that generated an exception on an untested unanticipated condition, rather than fall through to some essentially random default behavior, which is what happens with C'sswitch default behavior. It's very, very important that programs fail in a controlled manner when they encounter unanticipated conditions.Ok, I can (hopefully) see where you're not understanding our argument. AFAICT no-one's arguing for a C status-quo, which is what all your arguments seem to be addressing. Put in its simplest form: we want the compiler to force us to write a default, *in all cases*. My previous suggestion was to enable the syntactic sugar of substituting "unexpected:" for "default: assert(0);". (Note that "unexpected:" would throw something a little more informative than assert(0), perhaps an UnexpectedCaseException?)
Dec 02 2003
"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bqjr7a$197c$1 digitaldaemon.com...Ok, I can (hopefully) see where you're not understanding our argument. AFAICT no-one's arguing for a C status-quo, which is what all yourargumentsseem to be addressing.So, we all agree that C's implicit default:break; is not what we want? (This may cause some C code ported to D to have problems crop up. I think this is bearable, I just want to make sure it is known.) Does this also mean we agree that throwing a runtime exception on the default is not a bad thing if it is intended that cases cover all the bases?Put in its simplest form: we want the compiler to force us to write a default, *in all cases*.If this is our only point of disagreement on this, I don't think it's worthy of all the heat!My previous suggestion was to enable the syntactic sugar of substituting "unexpected:" for "default: assert(0);". (Note that "unexpected:" would throw something a little more informative than assert(0), perhaps an UnexpectedCaseException?)Actually, it throws a SwitchError exception, giving file name and line number.
Dec 08 2003
Walter wrote:I hate to make this more complicated, but ... I very much prefer the default;break; to the default;throw. Sorry! ;) I could settle for an explicit default requirement, but I don't like the exception at all. Here's why: From another one of your posts on this topic: Walter wrote:Ok, I can (hopefully) see where you're not understanding our argument. AFAICT no-one's arguing for a C status-quo, which is what all yourargumentsseem to be addressing.So, we all agree that C's implicit default:break; is not what we want? (This may cause some C code ported to D to have problems crop up. I think this is bearable, I just want to make sure it is known.) Does this also mean we agree that throwing a runtime exception on the default is not a bad thing if it is intended that cases cover all the bases?switch (value)I don't! Not at all. I believe that's a difference in our coding styles, or maybe the kind of applications we write, but I often use switch in cases where I want the function to do a task X in all cases, but in some cases do tasks A,B or C before that. That translates to a switch statement of the form: switch(bla) { case 1: doA(); break; case 2: doB(); break; case 3: doC(); break; [implicit default;break = do nothing for all other cases] } //always executed. doX(); I performed a search on some of my code and I found that switch statements where I really handle ALL cases are pretty rare. Especially in my networking-related applications there are a lot more switches of the kind I described above. Compiler software may be different, because, for example, you want to output an error if there is some unexpected token - but this doesn't apply to all kinds of software. You said you didn't want to force a particular coding style, so please don't force the way switch has to be used! Hauke{ case 1: blah(); break; case 2: foo(); break; case 3: bar(); break; }I view the above switch statement as explicitly saying "the only >possible values for value are 1, 2 or 3. No other values are possible. Therefore, it is a program bug if there are any other values."
Dec 09 2003
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:br4r11$2tdu$1 digitaldaemon.com...I hate to make this more complicated, but ... I very much prefer the default;break; to the default;throw. Sorry! ;) I could settle for an explicit default requirement, but I don't like the exception at all. Here's why: From another one of your posts on this topic: Walter wrote: >switch (value) >> { >> case 1: >> blah(); >> break; >> case 2: >> foo(); >> break; >> case 3: >> bar(); >> break; >> } >I view the above switch statement as explicitly saying "the only possible >values for value are 1, 2 or 3. No other values are possible. >Therefore, it >is a program bug if there are any other values." I don't! Not at all. I believe that's a difference in our coding styles,Yes, it's a clear difference in our styles of using switch statements. My experience in code reviews, however, is when there is no explicit default in the switch and I question the programmer about it, it's almost always an oversight (i.e. a bug).I performed a search on some of my code and I found that switch statements where I really handle ALL cases are pretty rare.Mine too, but I like to put in a default:break; to signal to anyone reading the code that I didn't just overlook the other cases!You said you didn't want to force a particular coding style, so please don't force the way switch has to be used!I wish I could please everyone on this, but it's not possible.
Dec 09 2003
"Walter" <walter digitalmars.com> wrote in message news:br53qk$98m$1 digitaldaemon.com..."Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:br4r11$2tdu$1 digitaldaemon.com...inI hate to make this more complicated, but ... I very much prefer the default;break; to the default;throw. Sorry! ;) I could settle for an explicit default requirement, but I don't like the exception at all. Here's why: From another one of your posts on this topic: Walter wrote: >switch (value) >> { >> case 1: >> blah(); >> break; >> case 2: >> foo(); >> break; >> case 3: >> bar(); >> break; >> } >I view the above switch statement as explicitly saying "the only possible >values for value are 1, 2 or 3. No other values are possible. >Therefore, it >is a program bug if there are any other values." I don't! Not at all. I believe that's a difference in our coding styles,Yes, it's a clear difference in our styles of using switch statements. My experience in code reviews, however, is when there is no explicit defaultthe switch and I question the programmer about it, it's almost always an oversight (i.e. a bug).So they should have put in a default, so the compiler should make them do so. QED. You just keep proving our point.
Dec 09 2003
This probably wont help any but a switch that acts like visual basics Select Case statement would be the my preferred method. Select Case Acts like so: Select Case Foo Case 1 DoSomething() Case 2,3,4,5 DoSomething() Case 10 DoSomething() Case Else Nothing Was Caught So Do A Default End Select What happens, is that it falls down thru till a match is found, an that matching statement is then executed... if nothing is found, the Case Else is excecuted. The Case Else is optional, so if nothing is matched, nothing is excecuted.
Dec 09 2003
Lewis Miller wrote:This probably wont help any but a switch that acts like visual basics Select Case statement would be the my preferred method. Select Case Acts like so: Select Case Foo Case 1 DoSomething() Case 2,3,4,5 DoSomething() Case 10 DoSomething() Case Else Nothing Was Caught So Do A Default End Select What happens, is that it falls down thru till a match is found, an that matching statement is then executed... if nothing is found, the Case Else is excecuted. The Case Else is optional, so if nothing is matched, nothing is excecuted.This is my preferred style as well. (Maybe it's from all of my experience in VB/VBA.) It handles the cases I ask it to handle. That's enough for me. Justin
Dec 09 2003
J C Calvarese wrote:Lewis Miller wrote:interestingly enough, vb also has a switch statement i.e i = Switch( Index , 1, 2, 3, 4, 5) Following that, i would say that it would be best to keep switch close to what it is, and add a new keyword (such as branch() i like) for a advanced switch statementThis probably wont help any but a switch that acts like visual basics Select Case statement would be the my preferred method. Select Case Acts like so: Select Case Foo Case 1 DoSomething() Case 2,3,4,5 DoSomething() Case 10 DoSomething() Case Else Nothing Was Caught So Do A Default End Select What happens, is that it falls down thru till a match is found, an that matching statement is then executed... if nothing is found, the Case Else is excecuted. The Case Else is optional, so if nothing is matched, nothing is excecuted.This is my preferred style as well. (Maybe it's from all of my experience in VB/VBA.) It handles the cases I ask it to handle. That's enough for me. Justin
Dec 09 2003
In article <br5b9g$l4b$1 digitaldaemon.com>, Lewis Miller says...This probably wont help any but a switch that acts like visual basics Select Case statement would be the my preferred method. Select Case Acts like so: Select Case Foo Case 1 DoSomething() Case 2,3,4,5 DoSomething() Case 10 DoSomething() Case Else Nothing Was Caught So Do A Default End Select What happens, is that it falls down thru till a match is found, an that matching statement is then executed... if nothing is found, the Case Else is excecuted. The Case Else is optional, so if nothing is matched, nothing is excecuted.I must agree with this approach. This, to my mind, is the right way (TM) to do switches/cases/selects. The C'ish approach smacks of hackery and danger (dangery? hackanger?). I've been working in a language other than C/C++ for ~2 years now professionally (game development, native code compiled language), and while it does resemble C++ in many ways, it implements switches as above. I must say I don't miss C's questionable switches *at all*. They seem quite bad to my mind, and I'm glad to have moved away from them. (hmm... what's this dead horse doing here?) Fall-through is bad! You never *ever* need it. If you reexamine all your switch statements in your own code and think of how they'd be done if fall-through were not allowed, I believe you will find that you could write clearer code once you've made the paradigm shift. Fall-through's are treacherous short-cuts and are bugs waiting to happen. They do not belong in a language that is attempting to increase code safety. The reuse of the 'break' keyword is confusing at best, and significantly dangerous at worse (see http://www.cs.berkeley.edu/~nikitab/courses/cs294-8/hw1.html for an example where a programmer expected the 'break' in a 'switch' to break out of an enclosing loop, causing a telephone system failure that ran up a $60 million loss). 'Break' should mean only one thing! Switch statements cases should break implicitly. Cases should be stackable as above to account for handling multiple cases exactly the same way. Goto's, explicit fall-throughs, and other (I bet that dead horse will think twice next time!) As for requiring a 'default' case, I think that is an extreme response to a specific problem. It really looks no different (to my eyes) than requiring an 'else' for every 'if'. Throwing an exception when a case isn't handled *will* force programmers to write safer code in general, but the cost is not insignificant. I can see both sides of this issue so I'll defer to Walter for the force of the argument. There, I've had my rant :) Dan L.
Dec 09 2003
Me too, I do not like that "break"'s in the switch. But I understand the others. Maybe Walter should add also a "branch" statement, where the rules are similar to Pascal's "case": no breaks (or the break should be implicit), "ranged" cases (i.e. case 1..8) etc. To meet all tastes... In article <br5ni9$189d$1 digitaldaemon.com>, Dan Liebgold says...In article <br5b9g$l4b$1 digitaldaemon.com>, Lewis Miller says...This probably wont help any but a switch that acts like visual basics Select Case statement would be the my preferred method. Select Case Acts like so: Select Case Foo Case 1 DoSomething() Case 2,3,4,5 DoSomething() Case 10 DoSomething() Case Else Nothing Was Caught So Do A Default End Select What happens, is that it falls down thru till a match is found, an that matching statement is then executed... if nothing is found, the Case Else is excecuted. The Case Else is optional, so if nothing is matched, nothing is excecuted.I must agree with this approach. This, to my mind, is the right way (TM) to do switches/cases/selects. The C'ish approach smacks of hackery and danger (dangery? hackanger?). I've been working in a language other than C/C++ for ~2 years now professionally (game development, native code compiled language), and while it does resemble C++ in many ways, it implements switches as above. I must say I don't miss C's questionable switches *at all*. They seem quite bad to my mind, and I'm glad to have moved away from them. (hmm... what's this dead horse doing here?) Fall-through is bad! You never *ever* need it. If you reexamine all your switch statements in your own code and think of how they'd be done if fall-through were not allowed, I believe you will find that you could write clearer code once you've made the paradigm shift. Fall-through's are treacherous short-cuts and are bugs waiting to happen. They do not belong in a language that is attempting to increase code safety. The reuse of the 'break' keyword is confusing at best, and significantly dangerous at worse (see http://www.cs.berkeley.edu/~nikitab/courses/cs294-8/hw1.html for an example where a programmer expected the 'break' in a 'switch' to break out of an enclosing loop, causing a telephone system failure that ran up a $60 million loss). 'Break' should mean only one thing! Switch statements cases should break implicitly. Cases should be stackable as above to account for handling multiple cases exactly the same way. Goto's, explicit fall-throughs, and other (I bet that dead horse will think twice next time!) As for requiring a 'default' case, I think that is an extreme response to a specific problem. It really looks no different (to my eyes) than requiring an 'else' for every 'if'. Throwing an exception when a case isn't handled *will* force programmers to write safer code in general, but the cost is not insignificant. I can see both sides of this issue so I'll defer to Walter for the force of the argument. There, I've had my rant :) Dan L.
Dec 09 2003
Lewis Miller wrote:This probably wont help any but a switch that acts like visual basics Select Case statement would be the my preferred method. Select Case Acts like so: Select Case Foo Case 1 DoSomething() Case 2,3,4,5 DoSomething() Case 10 DoSomething() Case Else Nothing Was Caught So Do A Default End Select What happens, is that it falls down thru till a match is found, an that matching statement is then executed... if nothing is found, the Case Else is excecuted. The Case Else is optional, so if nothing is matched, nothing is excecuted.This is my preference as well. I guess the D version would look slightly different, but it's the general idea that counts.
Dec 09 2003
In a recent post Walter wrote:While I generally agree with you here, the point I make is that the language should make the right thing to do the easiest thing to do.In another recent post Walter wrote:Mine too, but I like to put in a default:break; to signal to anyone reading the code that I didn't just overlook the other cases!These statements combined would seem to vote for an obligatory explicit default in switch statements? I think most of the time people don't put a default in their switch 'cause they forgot. The compiler could "remind" them. If one is stupid enough to put a default:break when they shouldn't, then it's their own fault. But most people would just remember that this was what they forgot, no biggie. Incidentally, I was one who got derailed with the assert(0) thing. That sounded really unfriendly. Throwing a proper error is much better, although I still vote for an obligatory and explicit default.
Dec 10 2003
C has an implicit default:break; ? Regardless, as I don't like your built-in assert(), I certainly don't want the compiler to add one. Why do you insist on not breaking ported C code in some cases, while going out of your way to break it in other cases? Make up your mind! In article <br3sjr$1ajv$2 digitaldaemon.com>, Walter says..."Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bqjr7a$197c$1 digitaldaemon.com...Ok, I can (hopefully) see where you're not understanding our argument. AFAICT no-one's arguing for a C status-quo, which is what all yourargumentsseem to be addressing.So, we all agree that C's implicit default:break; is not what we want? (This may cause some C code ported to D to have problems crop up. I think this is bearable, I just want to make sure it is known.) Does this also mean we agree that throwing a runtime exception on the default is not a bad thing if it is intended that cases cover all the bases?Put in its simplest form: we want the compiler to force us to write a default, *in all cases*.If this is our only point of disagreement on this, I don't think it's worthy of all the heat!My previous suggestion was to enable the syntactic sugar of substituting "unexpected:" for "default: assert(0);". (Note that "unexpected:" would throw something a little more informative than assert(0), perhaps an UnexpectedCaseException?)Actually, it throws a SwitchError exception, giving file name and line number.
Dec 09 2003
"The Lone Haranguer" <The_member pathlink.com> wrote in message news:br58dg$gms$1 digitaldaemon.com...C has an implicit default:break; ?Yes.Regardless, as I don't like your built-in assert(), I certainly don't wantthecompiler to add one. Why do you insist on not breaking ported C code in some cases, while goingoutof your way to break it in other cases? Make up your mind!I plead guilty to the inconsistency.
Dec 09 2003
I think that you are missing one of the central tenets of Walter's design of D. Quoted from http://digitalmars.com/d/overview.html, the First Major Goal of D is: <quote> Reduce software development costs by at least 10% by adding in proven productivity enhancing features and by adjusting language features so that common, time-consuming bugs are eliminated from the start. </quote> So, as I have seen over and over, Walter's intention is to design a language which makes it easy to do the Right Thing and hard(er) to do the Wrong Thing. He has made the language very C-like so that it is easy to port, but intentionally breaks things that he believes led to lots of bugs in C. In this discussion, we have seen a wide variety of opinions about what the Right Thing is; thus, we have had a lot of debate. I think it's fair to discuss with Walter about what the Right Thing is, but I don't think it's fair to call him inconsistent. C compatibility was never a stated goal. Hang in there, Walter! The current storm will subside. Russ The Lone Haranguer wrote:C has an implicit default:break; ? Regardless, as I don't like your built-in assert(), I certainly don't want the compiler to add one. Why do you insist on not breaking ported C code in some cases, while going out of your way to break it in other cases? Make up your mind! In article <br3sjr$1ajv$2 digitaldaemon.com>, Walter says..."Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bqjr7a$197c$1 digitaldaemon.com...Ok, I can (hopefully) see where you're not understanding our argument. AFAICT no-one's arguing for a C status-quo, which is what all yourargumentsseem to be addressing.So, we all agree that C's implicit default:break; is not what we want? (This may cause some C code ported to D to have problems crop up. I think this is bearable, I just want to make sure it is known.) Does this also mean we agree that throwing a runtime exception on the default is not a bad thing if it is intended that cases cover all the bases?Put in its simplest form: we want the compiler to force us to write a default, *in all cases*.If this is our only point of disagreement on this, I don't think it's worthy of all the heat!My previous suggestion was to enable the syntactic sugar of substituting "unexpected:" for "default: assert(0);". (Note that "unexpected:" would throw something a little more informative than assert(0), perhaps an UnexpectedCaseException?)Actually, it throws a SwitchError exception, giving file name and line number.
Dec 10 2003
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:br7rue$1gaa$2 digitaldaemon.com...Hang in there, Walter! The current storm will subside.Thanks! At the end of the day, I just have to make a decision and stick with it, or D will never move forward.
Dec 10 2003
Well, based on both those arguments, fall-through should be abandoned. I understood fall-through was left in for C compatibility, and it leads to many bugs. In article <br7rue$1gaa$2 digitaldaemon.com>, Russ Lewis says...I think that you are missing one of the central tenets of Walter's design of D. Quoted from http://digitalmars.com/d/overview.html, the First Major Goal of D is: <quote> Reduce software development costs by at least 10% by adding in proven productivity enhancing features and by adjusting language features so that common, time-consuming bugs are eliminated from the start. </quote> So, as I have seen over and over, Walter's intention is to design a language which makes it easy to do the Right Thing and hard(er) to do the Wrong Thing. He has made the language very C-like so that it is easy to port, but intentionally breaks things that he believes led to lots of bugs in C. In this discussion, we have seen a wide variety of opinions about what the Right Thing is; thus, we have had a lot of debate. I think it's fair to discuss with Walter about what the Right Thing is, but I don't think it's fair to call him inconsistent. C compatibility was never a stated goal. Hang in there, Walter! The current storm will subside. Russ
Dec 10 2003
I think perhaps this could be used as an argument for strongly-typed booleans too. The C practice of: int x = something ; if ( x ) ... ; or worse: char* s = something ; if ( s ) ... ; is at least poor style, and can lead to higher maintenance time and cost (due to maintenance being done by programmers less-experienced than the original programmers (who didn't write any comments because they feel that the code is the documentation)). <On my last job I had to deal with a lot of the latter example and always replaced them with if ( s != NULL ) ... ; > So, although it may not lead to bugs, it's the "Wrong Thing". And strongly-typed booleans should be the fix. And it seems the only reason to continue to allow it is because of portability with C. And furthermore, as mentioned before, strongly-typed booleans also solve the problem of when someone writes if ( x = y ) ... ; accidently. (Unless x and y are boolean, but how often would you do that?) Oh, sheesh, I'm still writing? Well let me get it over with here and not have to write another message. As mentioned before, yet another solution to the "assign instead of equality" mistake is to have a different assignment operator, e.g. := . At one point Walter said that makes sense. Again, it seems that the only reason to keep the "C assignment operator" is for portability! In article <br7rue$1gaa$2 digitaldaemon.com>, Russ Lewis says...I think that you are missing one of the central tenets of Walter's design of D. Quoted from http://digitalmars.com/d/overview.html, the First Major Goal of D is: <quote> Reduce software development costs by at least 10% by adding in proven productivity enhancing features and by adjusting language features so that common, time-consuming bugs are eliminated from the start. </quote> So, as I have seen over and over, Walter's intention is to design a language which makes it easy to do the Right Thing and hard(er) to do the Wrong Thing. He has made the language very C-like so that it is easy to port, but intentionally breaks things that he believes led to lots of bugs in C. In this discussion, we have seen a wide variety of opinions about what the Right Thing is; thus, we have had a lot of debate. I think it's fair to discuss with Walter about what the Right Thing is, but I don't think it's fair to call him inconsistent. C compatibility was never a stated goal. Hang in there, Walter! The current storm will subside. Russ
Dec 10 2003
Walter wrote:It's very, very important that programs fail in a controlled manner when they encounter unanticipated conditions.Nondeterministic bugs are great for burning a few hours (and brain cells) -- andy
Dec 02 2003
"Andy Friesen" <andy ikagames.com> wrote in message news:bqk3hl$1ldp$1 digitaldaemon.com...Walter wrote:Yup. That's why DbC is so valuable, as the earlier in the program the bug is detected the more likely it is deterministic.It's very, very important that programs fail in a controlled manner when they encounter unanticipated conditions.Nondeterministic bugs are great for burning a few hours (and brain cells)
Dec 08 2003
"Walter" <walter digitalmars.com> wrote in message news:bqjanc$gfp$1 digitaldaemon.com...It's very, very important that programs fail in a controlled manner when they encounter unanticipated conditions.I might accept your solution if you make a minor change. Don't use assert(0);! As a programmer I might sprinkle asserts in my code and when I do, I know that some of my code (or at least the user of my code) has made a mistake and I might start to look for the assert in question. But suddenly I get an assert exception that don't match an assert in my code! Can be nothing else than an compiler bug. And I suppose I will flag it as such if it ever happens to me. The exception thrown MUST be a well documented and well specified exception (like the UnknownSwitchCaseException suggested by Matthew). Even better, demand the default case at compile time. Then it will never be a problem at runtime! Lars Ivar Igesund
Dec 03 2003
I may be not getting this argument. I see Water saying: You can have a default case if you want to, it may do nothing. The normal default case will throw an exception. Others are saying: Let the default case be do nothing (like C/C++). And it's up to the programmer to explicity decide if the default case is an error. Personally I like the default exception method, it will catch bugs. But I can see how porting legacy code directly from C would possibly allow different kinds of bugs to slip through. Why not have a compiler switch that can enforce the requirement for a default case - then everyone wins. Those that like the fall through behaviour will get compile time errors & be forced to place empty default cases, those that like the default exception method can have that too. At the end of the day it's a programmer preference. Brad Lars Ivar Igesund wrote:"Walter" <walter digitalmars.com> wrote in message news:bqjanc$gfp$1 digitaldaemon.com...It's very, very important that programs fail in a controlled manner when they encounter unanticipated conditions.I might accept your solution if you make a minor change. Don't use assert(0);! As a programmer I might sprinkle asserts in my code and when I do, I know that some of my code (or at least the user of my code) has made a mistake and I might start to look for the assert in question. But suddenly I get an assert exception that don't match an assert in my code! Can be nothing else than an compiler bug. And I suppose I will flag it as such if it ever happens to me. The exception thrown MUST be a well documented and well specified exception (like the UnknownSwitchCaseException suggested by Matthew). Even better, demand the default case at compile time. Then it will never be a problem at runtime! Lars Ivar Igesund
lid Date
I may be not getting this argument. I see Water saying: You can have a default case if you want to, it may do nothing. The normal default case will throw an exception. Others are saying: Let the default case be do nothing (like C/C++). And it's up to the programmer to explicity decide if the default case is an error.That is not so. We're saying that the default must be specified. The logic is simple: 1. Omitting "default" can be problematic 2. Having default behaviour, that throws an exception, when "default" is ommitted can be problematic 3. Requiring default (or unexpected) be specified costs nothing but fewer maintenance keystrokes. As the yanks like to say: you do the math!Personally I like the default exception method, it will catch bugs.This is wrong. It will catch _some_ bugs, not all. Only mandatory default will catch all (unless the programmer is a f-wit, in which case ...)But I can see how porting legacy code directly from C would possibly allow different kinds of bugs to slip through.Not if it was mandatoryWhy not have a compiler switch that can enforce the requirement for a default case - then everyone wins.Walter won't have warnings, and wants to minimise the number of compilation modes. I agree with this. Given that stipulation, the clear position is to make the default (or unexpected) mandatory
Dec 03 2003
I've gone through reams of C code, and I am not convinced anymore about the break statement. It really seems like the vast majority of code does not need fallthrough, most of the switches are full of breaks. Actually, cases without break (ie they fall through to the next case) are much rarer than I originally thought. (Maybe textbooks overrepresent examples of this?) All fallthrough cases I found were empty themselves, so situations where there's some code in one case after which the code of the next is executed did not exist in my data. (Open Source from my Linux distro, a pseudorandom sample about 2.5M of c.) This really blew my previous conviction. So, now I jump into the "no break means break, fallthrough needs an explicit statement" gang. If we think near the metal, then the old break thing seems natural, but what we are aiming at is a higher level language here, so we gotta think outside the metal. Implicit break (heh, saves ink,) gives clearer code, and I admit, now seems to be less dangerous than demanding explicit break. Since the cases where you need fallthroug are comparatively rare, you sort of notice them, and there it is natural to have to write a word more. This change also suggests that we should allow lists in cases. This would also make it even rarer to need fallthrough. Actually, we might consider skipping fallthrough totally. The situations where you'd use it could be refactored, and we could leave the optimizing to the optimizer. (Or if you insist on living dangerously you could use (ohmigawd!) goto.) This warns me of another thing: earlier I pointed out that not being able to touch type should not influence our decisions about the language. Similarly, ingrained coding habits, our pet idioms, and "thinking in Pascal when writing Java" -- shouldn't either influence our current thinking about D!
Dec 03 2003
[warning: some of you might not find this idea appealing.] It was suggested before, and now I'd like to bring it up again. I don't think Walter will change the way switch works. Maybe he'll change the default: status, but fallthrough will remain, and that's because he wants some kind of C compatibility. (OT: btw, I don't agree with this. It's been said many times, and I repeat: people shouldn't just copy and paste C code for their D programs). So maybe the next logical thing would be to add a different kind of switch with all the things we all (by majority) have asked for: fallthrough, explicit default, ranges, multiple case values, etc. What the keyword might be, I don't know. Maybe Basic's select would fit. ————————————————————————— Carlos Santander --- Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.545 / Virus Database: 339 - Release Date: 2003-11-27
Dec 03 2003
Carlos Santander B. wrote:[warning: some of you might not find this idea appealing.] It was suggested before, and now I'd like to bring it up again. I don't think Walter will change the way switch works.I suspect you're right.Maybe he'll change the default: status, but fallthrough will remain, and that's because he wants some kind of C compatibility. (OT: btw, I don't agree with this. It's been said many times, and I repeat: people shouldn't just copy and paste C code for their D programs). So maybe the next logical thing would be to add a different kind of switch with all the things we all (by majority) have asked for: fallthrough, explicit default, ranges, multiple case values, etc. What the keyword might be, I don't know. Maybe Basic's select would fit.I think you might be on to something here. I think "select" would be a good keyword for this appealing new way to control the flow. This is how I'm forced to write it now: switch(varName) { case "icon": iconFilename = varValue; break; case "tooltip": toolTip = varValue; break; default: break; /* To prevent a runtime error if an invalid configuration setting is indicated. */ } Windows doesn't usually generate a GPF if you put something it doesn't understand in the system registry. I don't want my program to generate a runtime error if the user puts something untelligible in the configuration file. My program will just skip that line. This is how I'd like to write it: select(varName) { case "icon": iconFilename = varValue; case "tooltip": toolTip = varValue; /* If I wanted to include a default, I would have done so. */ } If the programmer wants an error to occur when a different value appears, they can specify it explicitly, case default: assert(0); <rant> Good programming practices can be encouraged by the language. Good programming practices can't be compelled. As the rules of a language approach compelling good practices, it would become unusable before it reached that apex. If I'm wrong on this, please tell me which language compels good practices, and tell me how much you like developing in that language. From my perspective, the only safe language for me is the one that I don't use. </rant> I'm not trying to be obnoxious; this is just the way I look at it. Justin————————————————————————— Carlos Santander
Dec 03 2003
"J C Calvarese" <jcc7 cox.net> wrote in message news:bqlash$d74$1 digitaldaemon.com...<rant> Good programming practices can be encouraged by the language. Good programming practices can't be compelled. As the rules of a language approach compelling good practices, it would become unusable before it reached that apex. If I'm wrong on this, please tell me which language compels good practices, and tell me how much you like developing in that language. From my perspective, the only safe language for me is the one that I don't use. </rant> I'm not trying to be obnoxious; this is just the way I look at it.I actually agree with you. D doesn't compel you to use good practices. Nowhere does D require you to use in and out contracts, class invariants, eshew pointers, etc. What it *does* do is provide facilities to make it easier to use the good practices than the bad ones. For example, using an out parameter is a better practice than passing an explicit pointer to the parameter. For another example, D lets you write quick and dirty programs that do no error checking on things like file open failures, disk write failures, etc. If such an error actually does happen, though, you get a nice message and the program terminates gracefully. This is quite unlike C, where if you forget to check for file open failures you're likely to get a seg fault, a hang, or other gloriously bad behavior. D is well suited to writing both quick-and-dirty programs as well as careful, thorough programs. I bet a lot of us write numerous one-shot dumb little utility quick-and-dirty programs (I know I do). There's a balance to be struck between a helpful compiler message and an annoying nag. Each of us obviously would want to draw that line in a slightly different place, but hopefully those lines aren't too far apart.
Dec 08 2003
Uh uh uh... The compiler _does_ require good practices (in your opinion) or, in my opinion, bad practices in some cases. e.g. if ( x = y ) which is flagged by the compiler and needs to have more code added to tell the compiler that that is what I meant -- _that's bad_ ! And, even worse, it breaks ported C code as well. In article <br3uce$1cvu$1 digitaldaemon.com>, Walter says...I actually agree with you. D doesn't compel you to use good practices. Nowhere does D require you to use in and out contracts, class invariants, eshew pointers, etc. What it *does* do is provide facilities to make it easier to use the good practices than the bad ones.
Dec 09 2003
The Lone Harnguer wrote:Uh uh uh... The compiler _does_ require good practices (in your opinion) or, in my opinion, bad practices in some cases. e.g. if ( x = y ) which is flagged by the compiler and needs to have more code added to tell the compiler that that is what I meant -- _that's bad_ ! And, even worse, it breaks ported C code as well.If C code porting was 100% supported by D, then we'd be back to C++. D need to break some C rules inorder to be better. IMHO An error message for if ( x = y ) is a good start, and it isn't to hard to fix. Hay, you can even find replace most of these with a good find-replace program. -Anderson
Dec 09 2003
Carlos Santander B. wrote:It was suggested before, and now I'd like to bring it up again. I don't think Walter will change the way switch works. Maybe he'll change the default: status, but fallthrough will remain, and that's because he wants some kind of C compatibility. (OT: btw, I don't agree with this. It's been said many times, and I repeat: people shouldn't just copy and paste C code for their D programs). So maybe the next logical thing would be to add a different kind of switch with all the things we all (by majority) have asked for: fallthrough, explicit default, ranges, multiple case values, etc. What the keyword might be, I don't know. Maybe Basic's select would fit.I suggested something like that a while ago. I'll just paste part of that post again here: """ If we wouldn't have the requirement to easily port C/C++ code to D (do we really have it?) I would like to suggest to ditch the classic switch statement completely and introduce a new construct with different syntax that is more consistent with the rest of the language. This would also solve the problem that different fallthrough behaviour might confuse C/C++ programmers, since it is immediately recognizable as a different thing. Maybe something like this: branch(expression) { on(1) someFunc(); on(2,3,5..8) { a=7; dostuff(a,true); } } Hmmm. I think the syntax would probably need some work, but it would have some benefits: - the on-blocks are real code blocks. Adding local variables to them works in the same way as it does anywhere else. - break is not used in this construct, so it could actually be used to break out of an outer loop. This is something that I quite often wanted to do in C++. Ok, it is not THAT much of an issue in D anymore, since we can break with a label but being able to do it without an explicit label improves readability, since it is immediately clear which loop is referred to. But since I don't see any chance that switch is ditched there is no real point to argue for such a statement anyway . """ Hauke
Dec 03 2003
Maybe something like this: branch(expression) { on(1) someFunc(); on(2,3,5..8) { a=7; dostuff(a,true); } } Hmmm. I think the syntax would probably need some work, but it would have some benefits: - the on-blocks are real code blocks. Adding local variables to them works in the same way as it does anywhere else. - break is not used in this construct, so it could actually be used to break out of an outer loop. This is something that I quite often wanted to do in C++. Ok, it is not THAT much of an issue in D anymore, since we can break with a label but being able to do it without an explicit label improves readability, since it is immediately clear which loop is referred to.I like it. I think branch is a good name as well.
Dec 03 2003
Me too, I like it. Maybe D should implement both versions: switch and branch. As do-while and while... In article <bqmebi$21sh$1 digitaldaemon.com>, Vathix says...Maybe something like this: branch(expression) { on(1) someFunc(); on(2,3,5..8) { a=7; dostuff(a,true); } } Hmmm. I think the syntax would probably need some work, but it would have some benefits: - the on-blocks are real code blocks. Adding local variables to them works in the same way as it does anywhere else. - break is not used in this construct, so it could actually be used to break out of an outer loop. This is something that I quite often wanted to do in C++. Ok, it is not THAT much of an issue in D anymore, since we can break with a label but being able to do it without an explicit label improves readability, since it is immediately clear which loop is referred to.I like it. I think branch is a good name as well.
Dec 04 2003
href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref /html/vclrfTheSwitchStatement.asp">solved</a> the problem by keeping the switch syntax, but disallowing fall-through. Instead you can do one of two things: you can stack case statements, like so: switch (index) { case 0: case 1: do_something(); break; } And you can goto another case, like so: switch (index) { case 0: do_something(); goto case 1; case 1: do_something_more(); break; } It doesn't address the question of throwing exceptions on unhandled cases, but it neatly solves most of the issues brought up so far. Can anyone give an example of some code that relies on the fall-through behavior that this won't solve? Dan L.
Dec 05 2003
Dan Liebgold wrote:href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref /html/vclrfTheSwitchStatement.asp">solved</a> the problem by keeping the switch syntax, but disallowing fall-through. Instead you can do one of two things: you can stack case statements, like so: switch (index) { case 0: case 1: do_something(); break; } And you can goto another case, like so: switch (index) { case 0: do_something(); goto case 1; case 1: do_something_more(); break; } It doesn't address the question of throwing exceptions on unhandled cases, but it neatly solves most of the issues brought up so far. Can anyone give an example of some code that relies on the fall-through behavior that this won't solve?Well, there's nothing that a goto can't "solve." :-) In fact, it's part of my own suggestion. ...which is: 1. case labels should allow enumerations: case 1, 3, 5: 2. case labels should allow ranges: case 6 .. 25: 3. the compiler should generate an implicit "break" at the end of each case - no fall-thrus, ever. 4. the programmer can use normal program labels and "goto" for every other need.
Dec 05 2003
The following is cut from D lexer.c: case '/': p++; switch (*p) { case '=': p++; t->value = TOKdivass; return; case '*': p++; while (1) { while (1) { switch (*p) { case '/': break; case '\n': loc.linnum++; p++; continue; case 0: case 0x1A: error("unterm. /* */"); p = end; t->value = TOKeof; return; default: p++; continue; } break; } p++; if (p[-2] == '*' && p - 3 != t->ptr) break; } continue; case '/': p++; .. It looks as if you really can't code a lexer if there were implicit breaks. But I think this would work the same with them? Of course an empty case should not get an implicit break. I'm too old to be sure, but is there any place in phobos where an implicit break would break the code? (No pun intended.)
Dec 05 2003
The D if-statement demands a {} instead of a semicolon. The switch statement could do the same with the default cause. Leave it out, and you get a compiler error. If you want to not do anything, then just write default {} and everyone should be happy. "It should not be impossible to excercise bad habits, it just shouldn't be too easy." PS, why doesn't the if statement issue a runtime exception at a missing {} ? Shouldn't the compiler behave the same in similar situations? :-)
Dec 05 2003
I like the cut of your jib "Georg Wrede" <Georg_member pathlink.com> wrote in message news:bqqpek$2cbs$1 digitaldaemon.com...The D if-statement demands a {} instead of a semicolon. The switch statement could do the same with the default cause. Leave it out, and you get a compiler error. If you want to not do anything, then just write default {} and everyone should be happy. "It should not be impossible to excercise bad habits, it just shouldn't be too easy." PS, why doesn't the if statement issue a runtime exception at a missing {} ? Shouldn't the compiler behave the same in similar situations? :-)
Dec 05 2003
The following should protect (at least newbies), and my future D students: ... case 0: .. break;case 1: .. break;case 2: .. break; case 50: case 51: case 52: .. break;case 79: .. break;case 80: ..
Dec 05 2003
Yuck, I hope I don't run up against any of your students, that's just uuuugly! In article <bqqt9t$2i0c$1 digitaldaemon.com>, Georg Wrede says...The following should protect (at least newbies), and my future D students: ... case 0: .. break;case 1: .. break;case 2: .. break; case 50: case 51: case 52: .. break;case 79: .. break;case 80: ..
Dec 05 2003
In article <bqr86c$b3$1 digitaldaemon.com>, Natsayer says...Yuck, I hope I don't run up against any of your students, that's just uuuugly!Yeah. That was the whole point. OTOH, during the first semester, these first year students have so much else to grasp, that finding a missing break in their own code is just unnecessary grief. The second semester, when they've gained some confidence in their coding we'll revisit the case statement and introduce fall-through. (IF, by that time, I have become convinced that there exist real-world reasons to it, outside nifty textbook examples!) I trust that the more talented students will find out how and when to use fall-through by themselves, but those who haven't might just be better off not using it. I'm also not going to teach about goto, by the same reason. In the limited time of a class, ther are more important things to teach. After all, they're there to learn how to program, and no class should teach every detail there is to a language just because they exist. I honestly believe D is an excellent first language. Maybe even better than Pascal (which actually was created for this very purpose)! D is also powerful enough to remain the main language through university. The other "obligatory languages" (Java C, C++, Lisp, whatever the particular university considers essential) should remain class-specific.
Dec 06 2003
Exactly. What could be simpler?It's very, very important that programs fail in a controlled manner when they encounter unanticipated conditions.I might accept your solution if you make a minor change. Don't use assert(0);! As a programmer I might sprinkle asserts in my code and when I do, I know that some of my code (or at least the user of my code) has made a mistake and I might start to look for the assert in question. But suddenly I get an assert exception that don't match an assert in my code! Can be nothing else than an compiler bug. And I suppose I will flag it as such if it ever happens to me. The exception thrown MUST be a well documented and well specified exception (like the UnknownSwitchCaseException suggested by Matthew). Even better, demand the default case at compile time. Then it will never be a problem at runtime!
Dec 03 2003
In article <bqkb30$21du$1 digitaldaemon.com>, Matthew Wilson wrote:There's been a lot of debate on the matter and a lot of different strong opinions, but I don't think we've still gone to the root of the problem. Namely: Which one is the primary usage of switch statement? One where you cover all the cases, or the one where you cover them only partially? Let's consider the alternatives. 1. If the programmer's intent is to cover all of the cases, then by default it should throw an exception if an unexpected value is encountered. Examples of this sort follow below. 2. If the intent is to cover only some of the cases, then the default behavior should do nothing. As an example of this: void handle_keypress(int code) { switch (code) { case 'q': quit(); break; case 'w': do_something_else; break; case ...: ...; // would not be needed if these kind of switches is common default: break; } } Here a default statement is required, and if it is not there, the programmer will notice very quickly when an exception flies. However, if it wouldn't be required (as in C/C++), not much harm would be done. Let's go back to the case 1: when we actually want to handle all cases. A classic representative of "handle all cases" comes when doing a switch over an enum: enum Weekday { mon, tue, wed, thu, fri, sat, sun } void handle(Weekday w) { switch (w) { case mon: handle_mon(); break; case tue: handle_tue(); break; // and so on... } } Now if you want to add a new weekday (ok, I might've picked my example a bit short-sightedly...), and forgot to add it to the switch statement, you should probably get an exception (or mayhap a warning, or even an error?) for not adding it to the switch statement. But this isn't often the way anyone should be programming at all. (Someone may disagree, though...) It's reasonably common to make Weekday a polymorphic object in this case: interface Weekday { void handle(); } class Monday : Weekday { void handle() { ... } } void handle(Weekday w) { w.handle(); } Then the 'missing case' of the switch statement won't be even left for the language runtime to notice, because it will be detected during the compilation! And everyone is happy. However, what if the value for the switch statement where we want to handle all possible cases doesn't come from the program itself but from outside, suppose while, say, lexing or parsing a source file in a compiler front-end, or maybe reading a file in some graphics format: void read_file() { File_Header hdr = get_header(); switch (hdr.bit_depth) { case 24: set_depth(24); break; case 16: ... break; case 15: ... break; case 8: ... break; // No default would have to be generated because we always want to // specify one: default: throw Invalid_File_Format_Exception( "Unknown bit depth " + hdr.bit_depth.to_string()); } } Ha! Here the automatically generated exception wouldn't help us anyway, because in this case we want to handle the default statement ourselves! So the only place where the automatically thrown exception does give any benefit is when there is an enum for which there is an excuse of not making it an object. Right? Then is there much sense in having the throw-exception behavior the default? Maybe someone knows good excuses? And I can't really say which of these cases (handle-all/handle-some) is the more common one. Maybe two different keywords were better from the documentative viewpoint. What do you people generally use "switch" for? -Antti P.S. By the way, to my ear the pascalese "case x of" sounds much like the case "now we're handling *all* of the possible alternatives". And the C-style "switch" really only deals with only some of the possible cases and is similar in semantics to if-elseif-elseif... withouth the final else.Exactly. What could be simpler?It's very, very important that programs fail in a controlled manner when they encounter unanticipated conditions.[a lot of debate] Even better, demand the default case at compile time. Then it will never be a problem at runtime!
Dec 03 2003
In Java we are used to the language runtime issuing exceptions for things that are out of the ordinary, such as: NullPointerException, ClassCastException, IndexOutOfBoundsException, etc. The use of the "assert(0)" as the default "default" clause is not really my beef. What I really want is to know exactly where the error happened. I can't know that if all I get is "Assertion Error" from the application. I need a stack trace to find out where this assertion happened. What would be even better is to use a better typed exception like this: default: throw new UnexpectedCaseException(caseValue); That way we can output the caseValue, an exception that makes sense. But even more important some very basic debug info like where the stinkin' exception was thrown is imperitive. Imagine having an application that has 100 switch statements, and they encounter this unexpected case with the default: assert(0) semantics. Debugging is a nightmare! Where to look? Which one of these 100 switch statements is the culprit? If it was the culprit, what was the value that caused the exception? These are very important pieces of information that I think would be more reasonable than a simple assert(0).
Dec 03 2003
"Berin Loritsch" <bloritsch d-haven.org> wrote in message news:bqks57$2pa4$1 digitaldaemon.com...The use of the "assert(0)" as the default "default" clause is not really my beef. What I really want is to know exactly where the error happened. I can't know that if all I get is "Assertion Error" from the application. I need a stack trace to find out where this assertion happened. What would be even better is to use a better typed exception like this: default: throw new UnexpectedCaseException(caseValue); That way we can output the caseValue, an exception that makes sense. But even more important some very basic debug info like where the stinkin' exception was thrown is imperitive.I agree. This is what D already does: C:\>type test.d void main() { switch (3) { case 1: break; } } C:\>dmd test \dm\bin\link test,,,user32+kernel32/noi; C:\>test Error: Switch Default test.d(4) C:\>
Dec 08 2003
"Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:bqk56n$1o0g$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:bqjanc$gfp$1 digitaldaemon.com...I apologize for speaking metaphorically, what actually happens is not an assert(0) but a SwitchError exception is thrown. It'll give the file and line number, too, so it shouldn't be hard to find where it's coming from.It's very, very important that programs fail in a controlled manner when they encounter unanticipated conditions.I might accept your solution if you make a minor change. Don't use assert(0);!The exception thrown MUST be a well documented and well specified exception (like the UnknownSwitchCaseException suggested by Matthew).I agree. And the documentation says: "If none of the case expressions match, and there is not a default statement, a SwitchException is thrown." www.digitalmars.com/d/statement.html#switch. <g> (Actually, the documentation is wrong, it's now a SwitchError.)Even better, demand the default case at compile time. Then it will never be a problem at runtime!I'm reluctant to do that from experience with Java's demands that all exceptions be handled. The result was people would just blindly insert catch(...) to shut up the compiler. The result was *worse* because now new exceptions that *needed* to be dealt with got silently swallowed. (I've had some long discussions with well-known Java gurus about this.) It was one of those things that looked great on paper, but failed in practice.
Dec 08 2003
I agree, esp. with the last point. Things are a lot clearer for me now. So, no "default" case required. In article <br3t6m$1bd1$1 digitaldaemon.com>, Walter says..."Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:bqk56n$1o0g$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:bqjanc$gfp$1 digitaldaemon.com...I apologize for speaking metaphorically, what actually happens is not an assert(0) but a SwitchError exception is thrown. It'll give the file and line number, too, so it shouldn't be hard to find where it's coming from.It's very, very important that programs fail in a controlled manner when they encounter unanticipated conditions.I might accept your solution if you make a minor change. Don't use assert(0);!The exception thrown MUST be a well documented and well specified exception (like the UnknownSwitchCaseException suggested by Matthew).I agree. And the documentation says: "If none of the case expressions match, and there is not a default statement, a SwitchException is thrown." www.digitalmars.com/d/statement.html#switch. <g> (Actually, the documentation is wrong, it's now a SwitchError.)Even better, demand the default case at compile time. Then it will never be a problem at runtime!I'm reluctant to do that from experience with Java's demands that all exceptions be handled. The result was people would just blindly insert catch(...) to shut up the compiler. The result was *worse* because now new exceptions that *needed* to be dealt with got silently swallowed. (I've had some long discussions with well-known Java gurus about this.) It was one of those things that looked great on paper, but failed in practice.
Dec 09 2003
Felix wrote:Yes and no. Being a Java guru, most of the issues resolve around people who do not know how to work with exceptions. Think about it. How many C++ guys understand exceptions and how to properly handle them, and how many Java guys understand exceptions and how to properly handle them? The thing is that the closer to the area of the thrown exception you are, the better chance you have of working around it. I actually think that RuntimeExceptions (AKA unchecked exceptions) can be more damaging to an application's stability than checked ones. Will there be newbies that don't know that catch(Throwable) is bad--I mean really bad? Of course there will be. There will always be new developers who have to learn the hard way. There will always be lazy developers who don't *want* to learn the proper way. These developers cause more issues for contienscious developers than anything else. Think about it, for some things it is obvious that an exception will be thrown. If you are opening a file to read, there is a chance that the file won't exist. If it doesn't, and you still try to open it, you *should* expect a FileNotFoundException, and you should handle it as close to the source of the problem as possible. If that file was supposed to be a configuration file, then we might have to abort the program with another exception. The exception is caused by the FileNotFoundException, but the reason the app aborted is a ConfigNotFoundException or something. We can get into all kinds of philisophical discussions, but broad sweeping statements are generally made by people who want to shade the facts toward their personal point of view. Could you use a knife to loosen a screw? Sure, but I wouldn't advise it. The point is that there are different tools for different jobs. Checked exceptions have their uses--and many times they are an elegant solution. Unchecked exceptions also have their uses. I have seen examples where either type of exception was the wrong tool for the job. Saying that it is "a failed experiment" is FUD. It fails to understand the problem or the proposed solutions. What you decide for this language is up to you--just don't base decisions on broad sweeping statements is all.I'm reluctant to do that from experience with Java's demands that all exceptions be handled. The result was people would just blindly insert catch(...) to shut up the compiler. The result was *worse* because now new exceptions that *needed* to be dealt with got silently swallowed. (I've had some long discussions with well-known Java gurus about this.) It was one of those things that looked great on paper, but failed in practice.
Dec 09 2003
"Berin Loritsch" <bloritsch d-haven.org> wrote in message news:br4q6i$2s7e$1 digitaldaemon.com...newI'm reluctant to do that from experience with Java's demands that all exceptions be handled. The result was people would just blindly insert catch(...) to shut up the compiler. The result was *worse* because nowhadexceptions that *needed* to be dealt with got silently swallowed. (I'veofsome long discussions with well-known Java gurus about this.) It was onewhoYes and no. Being a Java guru, most of the issues resolve around peoplethose things that looked great on paper, but failed in practice.do not know how to work with exceptions. Think about it. How many C++guysunderstand exceptions and how to properly handle them, and how many Javaguysunderstand exceptions and how to properly handle them?The Java gurus would tell me that *they themselves* would insert the catch(...)'s, even while publicly preaching against it. They knew all the arguments against doing such, as they came up with those arguments! It wasn't just an issue of ignorant/inexperienced Java coders. C++ has this problem with "const-correctness". People find themselves stuffing in const keywords and const casts willy-nilly to get the code to compile. (There are even jokes on the internet about this practice.) While the end result will then compile, it isn't exactly "const-correct", little was achieved by it, and I would hazard a guess that few non-trivial C++ programs are actually const-correct because of this.We can get into all kinds of philisophical discussions, but broad sweeping statements are generally made by people who want to shade the facts towardtheirpersonal point of view. Could you use a knife to loosen a screw? Sure,butI wouldn't advise it. The point is that there are different tools fordifferentjobs. Checked exceptions have their uses--and many times they are anelegantsolution. Unchecked exceptions also have their uses. I have seen examples where either type of exception was the wrong tool forthejob. Saying that it is "a failed experiment" is FUD. It fails tounderstandthe problem or the proposed solutions. What you decide for this languageisup to you--just don't base decisions on broad sweeping statements is all.While I generally agree with you here, the point I make is that the language should make the right thing to do the easiest thing to do. In Java, the right thing to do with checked exceptions is the most tedious thing to do. The easiest thing to do in Java is just do a catch(...) and forget about it. This is much, much worse than not catching an unexpected unchecked exception (and so letting the runtime eventually handle it). In fact, if I have my Java history right, the whole reason that the Java language eventually added unchecked exceptions at all was the discovery that requiring all exceptions to be checked was unworkable for just the reasons I described.
Dec 09 2003
(I'venewI'm reluctant to do that from experience with Java's demands that all exceptions be handled. The result was people would just blindly insert catch(...) to shut up the compiler. The result was *worse* because nowexceptions that *needed* to be dealt with got silently swallowed.hadonesome long discussions with well-known Java gurus about this.) It wasofThis is simply wrong. I hear about this from time to time, and it is invariably a lack of care or understanding on the part of the developer. I can't think of a single instance where I've had to violate const-correctness. The few times where I've used const-cast are where it's doing lazy eval, or updating member stats, both of which are perfectly valid. While your Java exceptions analogy may have some merit, using C++'s const-correctness does not.whoYes and no. Being a Java guru, most of the issues resolve around peoplethose things that looked great on paper, but failed in practice.do not know how to work with exceptions. Think about it. How many C++guysunderstand exceptions and how to properly handle them, and how many Javaguysunderstand exceptions and how to properly handle them?The Java gurus would tell me that *they themselves* would insert the catch(...)'s, even while publicly preaching against it. They knew all the arguments against doing such, as they came up with those arguments! It wasn't just an issue of ignorant/inexperienced Java coders. C++ has this problem with "const-correctness". People find themselves stuffing in const keywords and const casts willy-nilly to get the code to compile. (There are even jokes on the internet about this practice.) While the end result will then compile, it isn't exactly "const-correct", little was achieved by it, and I would hazard a guess that few non-trivial C++ programs are actually const-correct because of this.
Dec 09 2003
Matthew Wilson wrote:Maybe it was and they just didn't want to admit it. ;P Seriously, it isn't so much whether you catch(Exception) (more acceptable than catch(Throwable)) or not is not the major issue, it is what you do with it from there. If you rethrow things you don't intend to worry about right away, then all is good. For every one you can claim is doing it wrong even though they know better, I can point to several more that do it right--without complaint.The Java gurus would tell me that *they themselves* would insert the catch(...)'s, even while publicly preaching against it. They knew all the arguments against doing such, as they came up with those arguments! It wasn't just an issue of ignorant/inexperienced Java coders.I'm reluctant to do that from experience with Java's demands that all exceptions be handled. The result was people would just blindly insert catch(...) to shut up the compiler. The result was *worse* because nowAgain, this is why I call it FUD. You simply do not know. For everyone that is doing it right there are others that do it wrong. So what to do? IMO, make a better mechanism to handle these things. If you can't learn from what is out there. I would prefer to know about potential exceptions if I call a method--esp. if I can do something about it. For instance: "Ok this file doesn't exist, let's use this one as a backup". Or no config could be loaded so we are working with defaults. Whatever. If a method will throw a known exception I want something stronger than a comment to tell me about it. Things that are inadvertant errors such as illegal argument exceptions, bounds checking exceptions or other obvious runtime exceptions, then I don't want to know about them or worry about them. I think having a mix of both checked and unchecked exceptions provides a nice way to ensure things are working properly--within reason. So if you have some system generated exceptions for violations of code constraints, of course they should be unchecked. It is quite common for people to filter whatever they hear to fit their own little world. For example, if you don't want checked exceptions, ok. But give solid reasoning beyond so and so said... Have you worked with a well written system? Have you worked with a poorly written system? What was the *real* problem? 9 times out of 10 is was using the wrong tool for the job--not that the tool didn't exist. I brought up C++ exception handling (your catch(...) examples you keep listing) because I have run into fewer C++ developers who know how to properly work with exceptions than Java developers. There are a couple reasons for this observation. First is that many C++ developers use C libraries which force you to do a check on a status bit returned from a method. This results in code with a plethora of if(!methodCall()) {} error handling statements. The second main reason is that until the last couple of years there haven't been compilers that produced decent exception handling code. Lastly, I will say that I much prefer Java's version of the catchall statement than C++'s. Here is the main difference: C++: catch(...) { // how do I get the exception, and report info on it?!? } Java: catch(Exception e) { e.printStackTrace(); System.out.println( e.getClass().getName() ); // find the root cause Throwable cause = e; while (e.getCause() != null) { cause = e.getCause(); } } There are a number of things you can do to have a meaningful error reported and present the user with a nice message to make it easier to understand what to do. Should catch alls be avoided? sure, but I have seen them more often in C++ code I have had the pleasure of maintaining than Java.... The bottom line is EVERY language has its weaknesses. EVERY language has its strengths. Somethimes the same thing can be a weekness and a strength. It depends on how it is used. Making blanket statements is like throwing the baby out with the bath water.C++ has this problem with "const-correctness". People find themselves stuffing in const keywords and const casts willy-nilly to get the code to compile. (There are even jokes on the internet about this practice.) While the end result will then compile, it isn't exactly "const-correct", little was achieved by it, and I would hazard a guess that few non-trivial C++ programs are actually const-correct because of this.This is simply wrong. I hear about this from time to time, and it is invariably a lack of care or understanding on the part of the developer. I can't think of a single instance where I've had to violate const-correctness. The few times where I've used const-cast are where it's doing lazy eval, or updating member stats, both of which are perfectly valid. While your Java exceptions analogy may have some merit, using C++'s const-correctness does not.
Dec 09 2003
Berin Loritsch wrote:If a method will throw a known exception I want something stronger than a comment to tell me about it. Things that are inadvertant errors such as illegal argument exceptions, bounds checking exceptions or other obvious runtime exceptions, then I don't want to know about them or worry about them. I think having a mix of both checked and unchecked exceptions provides a nice way to ensure things are working properly--within reason.That won't suffice. The main problem I have with JAVA's forced throws clause is that it prevents proper use of interfaces. (There are other flaws, like the insane amount of throws clauses you get if the call hierarchy gets deep enough, but the interface problem is the most important one to me.) The main point in having interfaces is to abstract from the implementation. But if you have to define what kinds of errors can occur in the implementation, then you automatically limit the "back-ends" you can put behind it. A great example is if you want to implement an existing interface to forward calls over a network to a server and let the server perform the task. Suddenly there are a whole lot of additional errors, like "host not found", "connection lost" and stuff like that that were not anticipated by whoever wrote the original interface. So what you end up with is either ignoring such errors or wrapping them in an object of one of the "legal" classes. Both ways are bad. The first one hides errors and can have serious consequences for the ability of the program to work properly. The second one defeats the whole purpose of having different exception classes, as they often end up being wrapped in some unrelated exception type. After having been frustrated with this "feature" of JAVA multiple times I just decided to ignore it for my last project. In that program EVERY method has a "throws Exception" clause. I was just fed up with trying to keep up meaningful error handling in an interface-based program while the compiler was working against me. Hauke
Dec 09 2003
Here's an article on the topic: http://www.octopull.demon.co.uk/java/ExceptionalJava.html Also, I checked Java 1.0. There was a facility for unchecked exceptions in it, so I made a mistake saying it wasn't there. I apologize for the error. Here's another article: http://www.mindview.net/Etc/Discussions/CheckedExceptions
Dec 09 2003
Remind me, Walter. Why don't we have (optional) throws statements? It seems to me like they would be the best of both worlds - they would allow additional DBC (since 'throws' is essentially an out clause) without requiring people to use kludgy catch(...). I can imagine that this might be difficult to enforce since the compiler would have to analyze all called functions (unless, of course, they also have 'throws' clauses). OTOH, you could throw an assertion failure, just like you would when you failed any other out statement. (Russ ducks flaming arrows headed his way...) Russ Walter wrote:"Berin Loritsch" <bloritsch d-haven.org> wrote in message news:br4q6i$2s7e$1 digitaldaemon.com...newI'm reluctant to do that from experience with Java's demands that all exceptions be handled. The result was people would just blindly insert catch(...) to shut up the compiler. The result was *worse* because nowhadexceptions that *needed* to be dealt with got silently swallowed. (I'veofsome long discussions with well-known Java gurus about this.) It was onewhoYes and no. Being a Java guru, most of the issues resolve around peoplethose things that looked great on paper, but failed in practice.do not know how to work with exceptions. Think about it. How many C++guysunderstand exceptions and how to properly handle them, and how many Javaguysunderstand exceptions and how to properly handle them?The Java gurus would tell me that *they themselves* would insert the catch(...)'s, even while publicly preaching against it. They knew all the arguments against doing such, as they came up with those arguments! It wasn't just an issue of ignorant/inexperienced Java coders. C++ has this problem with "const-correctness". People find themselves stuffing in const keywords and const casts willy-nilly to get the code to compile. (There are even jokes on the internet about this practice.) While the end result will then compile, it isn't exactly "const-correct", little was achieved by it, and I would hazard a guess that few non-trivial C++ programs are actually const-correct because of this.We can get into all kinds of philisophical discussions, but broad sweeping statements are generally made by people who want to shade the facts towardtheirpersonal point of view. Could you use a knife to loosen a screw? Sure,butI wouldn't advise it. The point is that there are different tools fordifferentjobs. Checked exceptions have their uses--and many times they are anelegantsolution. Unchecked exceptions also have their uses. I have seen examples where either type of exception was the wrong tool forthejob. Saying that it is "a failed experiment" is FUD. It fails tounderstandthe problem or the proposed solutions. What you decide for this languageisup to you--just don't base decisions on broad sweeping statements is all.While I generally agree with you here, the point I make is that the language should make the right thing to do the easiest thing to do. In Java, the right thing to do with checked exceptions is the most tedious thing to do. The easiest thing to do in Java is just do a catch(...) and forget about it. This is much, much worse than not catching an unexpected unchecked exception (and so letting the runtime eventually handle it). In fact, if I have my Java history right, the whole reason that the Java language eventually added unchecked exceptions at all was the discovery that requiring all exceptions to be checked was unworkable for just the reasons I described.
Dec 09 2003
Walter wrote:While I generally agree with you here, the point I make is that the language should make the right thing to do the easiest thing to do. In Java, the right thing to do with checked exceptions is the most tedious thing to do. The easiest thing to do in Java is just do a catch(...) and forget about it.You don't need the experts to tell you that. I just took 2 randomly bought Java books from my bookshelf, and discover that they both teach the same practice... One being "Java 2 Wochenend Crashkurs" (MITP) and another "Java 2 Kompendium" (Markt&Technik). I believe the second is quite popular out here... And if the novices are not taught to get it right from beginning on, they probably realize that it's wrong when it's much too late. I'm somewhat thankful to parts of the library which don't force declaring eceptions on me... BTW, i've been rethinking my strategy about warnings ("nags")... I think now i'm more or less with you. The major difference to other warnings is though, that it is requiered to add these "throws" specifications not on one functiones, but on all which possibly can call it, including indirect calls, and that's what makes throw specification so evil. The number of changes requiered explodes with the growing project size. Change the underlying implementation of one function, so that the part of the library it uses may throw another exception, and there you have it - go ahead and correct the whole call tree. My current solution would be, to catch these exceptions with an assert if i don't expect them anyway... -eye --- rant --- 8< --- come to think of it, i don't know of a single Delphi book to teach questionable practices. however, C++ and java books teaching bad practice are quite common... while with c++ it is somehow explained by complexity - which is imo just a bad excuse for being unable to write a good book, or to get hands on writing a book for *novices* without understanding the language - for java it's really incredible... everyone knows, we should not do this and that, but we do and teach it anyway... that's where i can say the language is flawed... maybe another reason for good Delphi books is that they had to rival with the comprehensive, thought-through, wise manual (actually a tutorial book) delivered with each Delphi package? all delphi books seem to share a ton of similarity with that original work... something we should think about when it comes to our manuals someday. --- >8 ---
Dec 09 2003
In article <bqivh7$cr$1 digitaldaemon.com>, Walter says..."Ilya Minkov" <minkov cs.tum.edu> wrote in message news:bqaci5$2rl3$2 digitaldaemon.com...Requiring default will bring us to people typing "default: break;" instead of "default: assert(0)" just exactly for the reason you stated![...]Philosophically, I don't think a language is robust because it requires programmers to code in a certain way.You are contradicting your self because you are forcing programers to have a "defaul:assert(0);". even if they don't know about it![...]Ant
Dec 02 2003
"Ant" <Ant_member pathlink.com> wrote in message news:bqj3b0$5vc$1 digitaldaemon.com...You are contradicting your self because you are forcing programers to have a "defaul:assert(0);". even if they don't know about it!But D doesn't force them to explicitly write it! Sorry if I wasn't clear about that.
Dec 02 2003
In article <bqj778$bkj$1 digitaldaemon.com>, Walter says..."Ant" <Ant_member pathlink.com> wrote in message news:bqj3b0$5vc$1 digitaldaemon.com...You can't convince me on this one ;) I have nothing to add to mine or Mathew's first posts on this thread. Also I never saw you change your mind so I'm loosing hope on this one. (reverse psichology. again! but this time no spell check. didn't work the first time :) AntYou are contradicting your self because you are forcing programers to have a "defaul:assert(0);". even if they don't know about it!But D doesn't force them to explicitly write it! Sorry if I wasn't clear about that.
Dec 02 2003
"Ant" <Ant_member pathlink.com> wrote in message news:bqj888$d1r$1 digitaldaemon.com...You can't convince me on this one ;)I'll wait for when it finds an overlooked bug in your code <g>.
Dec 02 2003
"Walter" <walter digitalmars.com> wrote in message news:bqj778$bkj$1 digitaldaemon.com..."Ant" <Ant_member pathlink.com> wrote in message news:bqj3b0$5vc$1 digitaldaemon.com...So what? It does force them to have it. This is so bogus. You are forcing something on people that probably a lot of them do not want. How is that in keeping with the philosophy of not forcing things on people? Which is more odious, a forced compile-time restriction, or a forced runtime restriction?You are contradicting your self because you are forcing programers to have a "defaul:assert(0);". even if they don't know about it!But D doesn't force them to explicitly write it! Sorry if I wasn't clear about that.
Dec 02 2003
"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bqjqtm$18hg$2 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:bqj778$bkj$1 digitaldaemon.com...of"Ant" <Ant_member pathlink.com> wrote in message news:bqj3b0$5vc$1 digitaldaemon.com...So what? It does force them to have it. This is so bogus. You are forcing something on people that probably a lotYou are contradicting your self because you are forcing programers to have a "defaul:assert(0);". even if they don't know about it!But D doesn't force them to explicitly write it! Sorry if I wasn't clear about that.them do not want. How is that in keeping with the philosophy of notforcingthings on people? Which is more odious, a forced compile-time restriction, or a forcedruntimerestriction?I think both are odious for the switch, so as with all the runtime checks, they are not generated when compiled with -release. Though if one doesn't have a good test suite, it might be a good idea to not use -release and leave the runtime checks in.
Dec 08 2003
Walter wrote:"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bqjqtm$18hg$2 digitaldaemon.com...Walter, OK, I disagree with the current switch statement mostly in ways that are diametrically opposed to the opinion of Matthew Wilson, but I'm going to support his arguments since I see it as the lesser of "two evils" (so to speak): *Let's require a case on each switch statement.* This is better than the current situation of "random runtime errors" that I have. I'll come out and say it: I usually don't cover all of the case. I don't want to cover them all. (Oh, no! I must be a bad programmer.) If I'm reading in a simple little configuration file for a simple little application, I don't want a runtime error because the user puts an unknown setting in a line. I'll just ignore it. So I put "default: break;" at the end of the switch. So I'd rather D complain about it at compile time to remind me to add my "default: break;" and you and Matthew will remember to add your "default: assert(0);" If the errors are comping to occur due to my style of programming, I'd prefer them to appear at compile time when they're less embarrassing. (Of course, I'd argue going the opposite direction tommorrow -- hands-off compiling/no runtime checking -- if you show any signs of softening up on that idea.) Justin"Walter" <walter digitalmars.com> wrote in message news:bqj778$bkj$1 digitaldaemon.com...of"Ant" <Ant_member pathlink.com> wrote in message news:bqj3b0$5vc$1 digitaldaemon.com...So what? It does force them to have it. This is so bogus. You are forcing something on people that probably a lotYou are contradicting your self because you are forcing programers to have a "defaul:assert(0);". even if they don't know about it!But D doesn't force them to explicitly write it! Sorry if I wasn't clear about that.them do not want. How is that in keeping with the philosophy of notforcingthings on people? Which is more odious, a forced compile-time restriction, or a forcedruntimerestriction?I think both are odious for the switch, so as with all the runtime checks, they are not generated when compiled with -release. Though if one doesn't have a good test suite, it might be a good idea to not use -release and leave the runtime checks in.
Dec 09 2003
I think that you should not just code "any which way you want to" because your program will be full of bugs and will crash. There are plenty of programming "styles" that are just plain bad bad bad and should be prohibited. The compiler should try to help you get rid of bugs by detecting them at compile time, *before* you ship your application to millions of people. I realize this is not 100% possible. Sean "Walter" <walter digitalmars.com> wrote in message news:bqivh7$cr$1 digitaldaemon.com..."Ilya Minkov" <minkov cs.tum.edu> wrote in message news:bqaci5$2rl3$2 digitaldaemon.com...whoRequiring default will bring us to people typing "default: break;" instead of "default: assert(0)" just exactly for the reason you stated!A similar problem has happened with Java where it required you to list the possible exceptions generated by each function. Even expert programmerspublicly excoriated the practice would pepper their own code with generic catches just to shut up the compiler. The end result was that a rule that was supposed to increase robustness, actually wound up making thingsworse.Philosophically, I don't think a language is robust because it requires programmers to code in a certain way. I think it's robust if it allows programmers to program the way they want to, making robust programming practices easier to use than non-robust ones. For example, although Dallowsyou to use pointers as you would in C, D provides better semantic alternatives (like out parameters) that are more robust, and easier to use than the pointer equivalents. It's a win-win. One can counter this by saying "why do static type checking at all, then? Why not do it at runtime?" It's an excellent point, and the answer is that it's just too expensive to do at runtime. Languages that rely on runtime type checking tend to run very slowly compared with statically typed languages. As always, everything is a compromise in programming, and so we have static type checking in D.
Dec 03 2003
Following is Walters reasoning why the default checking can't be done at compile time. The thing is that we should either make default required all the time--which is an easy compile-time check--or follow normal switch semantics. Otherwise you will run into folks who only want to run some processing in one of a few cases, but ignore all other cases, and wonder why there is some sort of runtime exception being thrown. If you still want something that is runtime checked for these types of things, perhaps make it a feature of compiling with debug info in place that a message would be output to the system error stream with enough debug info to know a) what the value of the variable was, b) where the problem occurred. That way, there is enough information not only to know something is up, but to intelligently decide if it is really a problem or not. Walter wrote:"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bq65gu$2n8o$1 digitaldaemon.com...errors,Have to agree here, I rareley ( never ? ) use exceptions , and dont like them being thrown without my knoweldge / consent.Exactamundo, my friend. Exceptions are great for somethings, including actual serious/fatalor when doing stuff like deep-level parsing. Where they are absolutely not appropriate - and I can't believe this isevena discusson - is a runtime report of a code-time mistake!!There's no way to detect the error at compile time. What it's for is when one has: switch (x) { case 1: ... case 2: ... case 3: ... } and then one day x has the value 4. In C, there's an implicit default:break; inserted when no default is explicitly supplied. But in my experience coding, debugging my own mistakes, and fixing other peoples' code, the implicit default break is almost always the WRONG thing to happen, and then something unexpected happens as a result (i.e. crash, data corruption, etc.). When I see C code like that, and can ask the author, the intention is that x will always be 1, 2 or 3 and NEVER anything else. That's why he wrote the switch that way. That's ok, but then the maintenance programmer adds a feature where x is 4, updates all the switch statements accordingly, but inevitably misses one in the 100,000 line program he's revising. Even if the original coder INTENDED to make use of the implicit default:break;, it has that distinct odor of a bug, and so I flag it in code reviews. And in my experience, it was never intended. For years, I've advocated 'defensive programming' in C by making it explicit that the default case can never happen with: switch (x) { case 1: ... case 2: ... case 3: ... default: assert(0); } This is the normal practice in my own code. There are 3 situations to deal with, the above one, and: switch (x) { case 1: ... case 2: ... case 3: ... default: break; } and: switch (x) { case 1: ... case 2: ... case 3: ... default: do something break; } What D does is make it easy to ensure that all the bases are covered by with a random crash from forgetting to deal with a case. The compiler cannot do this at compile time because it has no way of determining all possible values x can take. In that way, it's similar to run time array bounds checking. The only other way of doing this with a hope of robustness is to *require* an explicitly written default statement for every switch. This would certainly be a valid language strategy, but I don't really want to be nagged by the compiler to insert a default:assert(0); when I know darn well that x can never be 4 <g>.
Dec 01 2003
Matthew Wilson wrote:Sounds like it is calling for a compiler check to me. I don't mind if the switch statement REQUIRES a default statement--as long as the compiler reports the problem.Have to agree here, I rareley ( never ? ) use exceptions , and dont like them being thrown without my knoweldge / consent.Exactamundo, my friend. Exceptions are great for somethings, including actual serious/fatal errors, or when doing stuff like deep-level parsing. Where they are absolutely not appropriate - and I can't believe this is even a discusson - is a runtime report of a code-time mistake!!
Dec 01 2003
How about a different word for case, like bcase, casex, fcase or ... briefcase. I don't know. switch(foobar) { case 3: normalFallThrough(); bcase 4: breaksAfterThis(); bcase 5, 6, 7: goodIdea(); default: yes(); }
Sep 16 2003
My Humble Opinion re: switch: 1. Individual cases should support enumerations and ranges. Like this: case 1, 2, 3: // switch values is 1, 2, or 3 case 50 .. 100: // switch value between 50 and 100 inclusive 2. All cases should imply break. 3. All other needs are well satisfied with goto. Yes, I said goto. In my experience, 90+% of the need for fallthru is to support enumerations, so I'd definitely lobby for that support. The case ranges allow switch to be used for more things that if/elseif/else has been used for, leading to the possibility of better diagnostics and greater language optimization. And when all else fails, there's goto. Yes, it's hated, which puts pressure on the programmer to think harder to make sure that it's really needed, and that's a GOOD thing because it's probably not. But if they can justify it, then it's right there, available for use.
Sep 17 2003
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1"> <title></title> </head> <div class="moz-text-html" lang="x-western"> Ian Woollard wrote:<br> <blockquote type="cite" cite="midbk5pk9$1a54$1 digitaldaemon.com"> <pre wrap="">In article <a class="moz-txt-link-rfc2396E" href="mailto:bk5o47$15o3$1 digitaldaemon.com"><bk5o47$15o3$1 digita daemon.com></a>, Charles Sanders says... </pre> <blockquote type="cite"> <pre wrap="">I like the idea of a nobreak statement ( this has been a popular topic) , I think the reason for keeping this is backward compatibility ( on a user level ). </pre> </blockquote> <pre wrap=""><!----> Provided the nobreak statement is optional (just a nasty compiler warning if left out), or mandatory but the compiler has a flag to make it ignore it's omission (but still warn- my colleagues ARE out to get me :-) ), then backward compatibility is, in practice, a non issue. </pre> <blockquote type="cite"> <pre wrap="">Charles "Ian Woollard" <a class="moz-txt-link-rfc2396E" href="mailto:Ian_member pathlink.com"><Ian_member pathlink.com></a> wrote in message <a class="moz-txt-link-freetext" href="news:bk5nri$14cm$1 digitaldaemon.com">news:bk5nri$14cm$1 digitaldaemon.com</a>... </pre> <blockquote type="cite"> <pre wrap="">Just had a quick look at the switch statement. I noticed the syntax is: switch (foobar) { case 0: dostuff(); // I've forgotten to break; all is lost. case 1: domorestuffIdidntreallywantto(); break; default: } This isn't such a good idea. The default behaviour is really unsafe. I </pre> </blockquote> <pre wrap="">would </pre> <blockquote type="cite"> <pre wrap="">suggest a 'nobreak' statement for cases where you really do want the code </pre> </blockquote> <pre wrap="">to </pre> <blockquote type="cite"> <pre wrap="">fall through; otherwise the compiler probably should fail to compile </pre> </blockquote> <pre wrap="">(possibly </pre> <blockquote type="cite"> <pre wrap="">switcheable off with a compiler option.) e.g. switch (foobar) { case 0: dostuff(); nobreak; // we fall through, but that's fine. case 1: case 2: // note no nobreak required (although I wouldn't cry if it was) domorestuff(); break; default: } Anyway, just an idea; probably a very good one IMNHO though. You might also consider the same idea in empty if and for statements. -Ian </pre> </blockquote> <pre wrap=""> </pre> </blockquote> <pre wrap=""><!----> </pre> </blockquote> I agree that the c switch state is error prone. There has been quite a bit of debate about changing the switch statement. However, your idea seems fresh. <br> I'd also be nice to do ranges on case statments such as 0..10, comment separators and greater that/less then operators (>=, >, <, <=).<br> <br> Anderson<br> <br> PS - Sorry Ian for posting to you, it's this new newsgroup program I'm using, I'm not used to the position of the "send to newsgroup". </div> </body> </html>
Sep 17 2003
Does anyone disagree that C/C++'s switch semantics are dangerous, even if the (we) old farts have gotten used to it and rarely get bitten? Does anyone think that it should be fixed in a way where implicit dangers still lurk for the unwary, whether that be inability to grok the new dangers, or the inability to get out of the mindset of the old (C/C++) semantics? Isn't the only sensible approach to have the compiler enforce the semantics, and not allow any possibility of mistakes on our part? Given that, why don't we simply accept the reality and have something along the lines: 1. Each case must end in break, throw, return, fallthrough or goto 2. The default case must be included. At first blush it seems nice to allow default to be skipped when switching on an enum if all enum values are given cases. However, since they might be updated in one bit of client code after the creation of the object code containing the switch, this is probably not wise. Maybe this is where Walter's exception would get thrown. But I think this stinks (and I'm not alone), so I'd rather see either the default be required and the code explicitly request that the exception be throw, or we could have another case keyword unexpected // 1, using default int i switch(i) { case 1: func1(); break; case 2: fallthrough: // I guess all you vowelly-challenged western-hemisperians would probably go for fallthru here ... ;) case 3: func2_3(); return; case 4: throw Some4Exception(); case 5: goto label 5; default: break; // A null default } // 2, using unexpected enum V { a, b, c, d } V v; switch(v) { case a: func1(); break; case b: fallthrough: // I guess all you vowelly-challenged western-hemisperians would probably go for fallthru here ... ;) case c: func2_3(); return; case d: throw Some4Exception(); unexpected: // This doesn't have any contents (and it's an error to have them), since it throws the exception that's currently thrown } Doesn't that cover every requirement that's been enunciated in this thread, whilst preventing any implicit behaviour whatsoever. The cost to these huge (IMO) benefits is that one must write default, or unexpected. Ouch! That's really going to slow down development times! "Ian Woollard" <Ian_member pathlink.com> wrote in message news:bk5nri$14cm$1 digitaldaemon.com...Just had a quick look at the switch statement. I noticed the syntax is: switch (foobar) { case 0: dostuff(); // I've forgotten to break; all is lost. case 1: domorestuffIdidntreallywantto(); break; default: } This isn't such a good idea. The default behaviour is really unsafe. Iwouldsuggest a 'nobreak' statement for cases where you really do want the codetofall through; otherwise the compiler probably should fail to compile(possiblyswitcheable off with a compiler option.) e.g. switch (foobar) { case 0: dostuff(); nobreak; // we fall through, but that's fine. case 1: case 2: // note no nobreak required (although I wouldn't cry if it was) domorestuff(); break; default: } Anyway, just an idea; probably a very good one IMNHO though. You might also consider the same idea in empty if and for statements. -Ian
Nov 28 2003
"Matthew Wilson" <matthew.hat stlsoft.dot.org> wrote in message news:bq8dbs$it$1 digitaldaemon.com..., or we could have another case keyword unexpectedI like! Lars Ivar Igesund
Nov 29 2003
I think the principle of the easiest thing would mean that we have the compiler require the "default" statement. That would require the developer to think about what will happen if something other than the expected happens. It is easier than finding out about it the hard way. The important thing to realize is that D is the only language I am aware of where the lack of a default clause to handle errors of this type will throw an exception. The number of people who will be caught by this trap is staggering. Perl, Python, etc. Please, if it is an error not to handle all switch types, require the developer to put in the default statement. If nothing else, they can output some debug info to the std err stream. Matthew Wilson wrote:Does anyone disagree that C/C++'s switch semantics are dangerous, even if the (we) old farts have gotten used to it and rarely get bitten? Does anyone think that it should be fixed in a way where implicit dangers still lurk for the unwary, whether that be inability to grok the new dangers, or the inability to get out of the mindset of the old (C/C++) semantics? Isn't the only sensible approach to have the compiler enforce the semantics, and not allow any possibility of mistakes on our part? Given that, why don't we simply accept the reality and have something along the lines: 1. Each case must end in break, throw, return, fallthrough or goto 2. The default case must be included. At first blush it seems nice to allow default to be skipped when switching on an enum if all enum values are given cases. However, since they might be updated in one bit of client code after the creation of the object code containing the switch, this is probably not wise. Maybe this is where Walter's exception would get thrown. But I think this stinks (and I'm not alone), so I'd rather see either the default be required and the code explicitly request that the exception be throw, or we could have another case keyword unexpected<snip/>
Dec 01 2003
Hear, hear! You've put it better than I did in any of my rants. :) "Berin Loritsch" <bloritsch d-haven.org> wrote in message news:bqfjgb$10o9$1 digitaldaemon.com...I think the principle of the easiest thing would mean that we have thecompilerrequire the "default" statement. That would require the developer tothinkabout what will happen if something other than the expected happens. Itiseasier than finding out about it the hard way. The important thing to realize is that D is the only language I am awareofwhere the lack of a default clause to handle errors of this type willthrowan exception. The number of people who will be caught by this trap is staggering. Perl, Python, etc. Please, if it is an error not to handle all switchtypes,require the developer to put in the default statement. If nothing else, they can output some debug info to the std err stream. Matthew Wilson wrote:ifDoes anyone disagree that C/C++'s switch semantics are dangerous, evendangersthe (we) old farts have gotten used to it and rarely get bitten? Does anyone think that it should be fixed in a way where implicitsemantics,still lurk for the unwary, whether that be inability to grok the new dangers, or the inability to get out of the mindset of the old (C/C++) semantics? Isn't the only sensible approach to have the compiler enforce thealongand not allow any possibility of mistakes on our part? Given that, why don't we simply accept the reality and have somethingswitchingthe lines: 1. Each case must end in break, throw, return, fallthrough or goto 2. The default case must be included. At first blush it seems nice to allow default to be skipped whenbeon an enum if all enum values are given cases. However, since they mightnotupdated in one bit of client code after the creation of the object code containing the switch, this is probably not wise. Maybe this is where Walter's exception would get thrown. But I think this stinks (and I'malone), so I'd rather see either the default be required and the code explicitly request that the exception be throw, or we could have another case keyword unexpected<snip/>
Dec 01 2003
In article <bqfjgb$10o9$1 digitaldaemon.com>, Berin Loritsch says...I think the principle of the easiest thing would mean that we have the compiler require the "default" statement.If nothing else, they can output some debug info to the std err stream.Maybe the compiler could add that instead of throwing a fatal error. during compilation the module name and the line number are available. Ant
Dec 01 2003