December 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 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...
>
>


December 08, 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.

Hauke





> 
> 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...
> 
> 
> 

December 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:
> > 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.
>
> Hauke
>
>
>
>
>
> >
> > 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...
> >
> >
> >
>


December 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


December 08, 2003
Ant wrote:

>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
>
>
>  
>
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.

December 08, 2003
J Anderson wrote:
>>> 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
>>
>>
>>  
>>
> Here'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.
> }

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 ;).

Hauke
December 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...
>> 
>>
>>>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
>>
>>
>> 
>>
>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.
>


December 08, 2003
Hauke Duden wrote:

> J Anderson wrote:
>
>>>> 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
>>>
>>>
>>>  
>>>
>> Here'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.
>> }
>
>
> 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 ;).
>
> Hauke

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.

December 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




December 09, 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 done
anyway)

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.