July 06, 2009
Denis Koroskin wrote:
> On Mon, 06 Jul 2009 22:48:07 +0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> 
>> Chad J wrote:
>>> Walter Bright wrote:
>>>> grauzone wrote:
>>>>> No. Also, this final switch feature seems to be only marginally
>>>>> useful, and normal switch statements do the same, just at runtime. So
>>>>> much for "more pressing issues" but it's his language and not mine so
>>>>> I'll shut up.
>>>> The final switch deals with a problem where you add an enum member in
>>>> one file and then have to find and update every switch statement that
>>>> uses that enum. There's no straightforward way to find them to ensure
>>>> the case gets added to each switch.
>>>>
>>>> It's solving a similar problem that symbolic constants do.
>>>>
>>>>
>>>> The fall-through thing, though, is purely local and so much less of an
>>>> issue.
>>>  huh?
>>>  These bugs always take me no less than 2 hours to find, unless I am
>>> specifically looking for fall-through bugs.
>>
>> I agree. Probably a good option would be to keep on requiring break, but
>> also requiring the user to explicitly specify they want fallthrough in
>> the rare case when they do want it. I'd love to use "continue" for that
>> but it's already "occupied" by cases like while (...) switch (...).
>> Requiring !break or ~break would work but is a bit too cute. Adding a
>> new keyword or a whole new switch statement is too much aggravation. I
>> guess we'll have to live with it...
>>
>>
>> Andrei
> 
> Reuse goto?

I was thinking "continue case;"

But of course this discussion is pointless because it's bikeshed idontknow...
July 06, 2009
On Mon, 06 Jul 2009 11:02:12 -0700, Walter Bright wrote:

> Derek Parnell wrote:
>> Safety is supposed to be enhance by using D, is it not?
> 
> See my post to Denis. Requiring too many casts reduces safety by essentially disabling the static type checking system.

I totaly agree that cast() should be avoided, almost at all costs. A better way in this situation is to use a variable that can accommodate the range of possible values. Only use the cast() construct if you are deliberately doing something other than normal.

For example, if you know that the different between two addresses will always be less than a 16-bit value AND you are deliberately storing the difference in a 'short' then using a cast() is a good idea as it alerts the code reader to this unusual situation.

   short x = cast(short)(p1 - p2);

However,

   auto x = p1 - p2;

should imply that 'x' is able to hold any value from -(uintptr_t.max) to
uintptr_t.max inclusive.

-- 
Derek Parnell
Melbourne, Australia
skype: derek.j.parnell
July 06, 2009
BCS wrote:
> The much worse class of bugs is the ones that you can be staring at the location of the bug, have an epiphany about what the bug is and still not be able to tell if it is the case: the bug is here, but cause by a line of code that could be anywhere.

If I understand that correctly, it's when you alter one line or declaration in one part of the code, and it silently breaks another piece of code far away in some other piece of not-obviously-related code.

I tend to agree.

It's why we don't hardcode array dimensions outside of the declaration - we started out in C by using a #define for it, and then in D encode the array dimension as part of the type. A local issue is one that has no adverse effects outside of the local context. The fall-through would be this. A non-local one is one like adding an enum case, because it can silently break code far away.

D makes some significant progress in reducing the non-local effects of changes, and is one of the big improvements over using C and C++.
July 06, 2009
Denis Koroskin wrote:
> Reuse goto?

So any case-labeled code should end either with a control flow statement that transfers control elswhere? That sounds like a great idea. Fall-through is so rare and so rarely intended, it makes sense to require the programmer to state the intent explicitly via a goto case.

Andrei
July 06, 2009
On Mon, 06 Jul 2009 13:47:44 -0500, Andrei Alexandrescu wrote:

> Chad J wrote:
>> Walter Bright wrote:
>>> grauzone wrote:
>>>> No. Also, this final switch feature seems to be only marginally useful, and normal switch statements do the same, just at runtime. So much for "more pressing issues" but it's his language and not mine so I'll shut up.
>>> The final switch deals with a problem where you add an enum member in one file and then have to find and update every switch statement that uses that enum. There's no straightforward way to find them to ensure the case gets added to each switch.
>>>
>>> It's solving a similar problem that symbolic constants do.
>>>
>>>
>>> The fall-through thing, though, is purely local and so much less of an issue.
>> 
>> huh?
>> 
>> These bugs always take me no less than 2 hours to find, unless I am specifically looking for fall-through bugs.
> 
> I agree. Probably a good option would be to keep on requiring break, but also requiring the user to explicitly specify they want fallthrough in the rare case when they do want it. I'd love to use "continue" for that but it's already "occupied" by cases like while (...) switch (...). Requiring !break or ~break would work but is a bit too cute. Adding a new keyword or a whole new switch statement is too much aggravation. I guess we'll have to live with it...

"too much aggravation" for whom? Certainly not for the coder, IMO.

Consider this syntax suggestion ...

  int x = 1;
  switch (x; fallthru) {
     case 1:
           write(1);
     case 2:
           write(2);
  }

Output: 12


  int x = 1;
  switch (x; break) {
     case 1:
           write(1);
     case 2:
           write(2);
  }

Output: 1

  int x = 1;
  switch (x; fallthru) {
     case 1:
           write(1);
           break;
     case 2:
           write(2);
  }

Output: 1


  int x = 1;
  switch (x; break) {
     case 1:
           write(1);
           fallthru;
     case 2:
           write(2);
  }

Output: 12

The default case
  "switch (x) {"
would be the same as
  "switch (x; fallthru) {".

One new keyword, and not a standard English word, allows all bases to be covered. Too much aggravation for whom?


By the way, the above syntax format suggestion is because I see that the
syntax for 'switch' is ...

   switch ( Expression ) ScopeStatement

and ScopeStatement is either a BlockStatement or a NonEmptyStatement. Meaning that

  switch (i) j = k;

is valid syntax! Why is that?

-- 
Derek Parnell
Melbourne, Australia
skype: derek.j.parnell
July 06, 2009
Derek Parnell wrote:
> On Mon, 06 Jul 2009 13:47:44 -0500, Andrei Alexandrescu wrote:
> 
>> Chad J wrote:
>>> Walter Bright wrote:
>>>> grauzone wrote:
>>>>> No. Also, this final switch feature seems to be only marginally
>>>>> useful, and normal switch statements do the same, just at runtime. So
>>>>> much for "more pressing issues" but it's his language and not mine so
>>>>> I'll shut up.
>>>> The final switch deals with a problem where you add an enum member in
>>>> one file and then have to find and update every switch statement that
>>>> uses that enum. There's no straightforward way to find them to ensure
>>>> the case gets added to each switch.
>>>>
>>>> It's solving a similar problem that symbolic constants do.
>>>>
>>>>
>>>> The fall-through thing, though, is purely local and so much less of an
>>>> issue.
>>> huh?
>>>
>>> These bugs always take me no less than 2 hours to find, unless I am
>>> specifically looking for fall-through bugs.
>> I agree. Probably a good option would be to keep on requiring break, but also requiring the user to explicitly specify they want fallthrough in the rare case when they do want it. I'd love to use "continue" for that but it's already "occupied" by cases like while (...) switch (...). Requiring !break or ~break would work but is a bit too cute. Adding a new keyword or a whole new switch statement is too much aggravation. I guess we'll have to live with it...
> 
> "too much aggravation" for whom? Certainly not for the coder, IMO.
> 
> Consider this syntax suggestion ...
[snip]

Well, I think I'd call that aggravation.

Andrei
July 06, 2009
Andrei Alexandrescu wrote:
> Chad J wrote:
>>
>> These bugs always take me no less than 2 hours to find, unless I am specifically looking for fall-through bugs.
> 
> I agree. Probably a good option would be to keep on requiring break, but also requiring the user to explicitly specify they want fallthrough in the rare case when they do want it. I'd love to use "continue" for that but it's already "occupied" by cases like while (...) switch (...). Requiring !break or ~break would work but is a bit too cute. Adding a new keyword or a whole new switch statement is too much aggravation. I guess we'll have to live with it...
> 
> 
> Andrei

Don't marginalize something that's important!

The syntax is arbitrary.  Just pick something that works.

Also, IIRC, the main argument in favor of fallthrough behavior was compatibility with C code.  Now that we have "final switch", we can, with reasonable certainty, assume that no C coder has written "final switch(...) ...".  Thus we are allowed to choose a syntax that's different without breaking anything.  And for those few people that want to write Duff's device, they can just use the old style switch-case.

<rambling and syntax>
I'm personally a bit biased to the haXe switch-case statements that I've
been using for the past few months.  In haXe you don't even have to
write break; at the end, it will always exit the statement at the end of
a case-block.  It also has that behavior added in final switch where
switching on an enum requires you to be exhaustive about your handling
of the possibilities.  It has worked well.  If it isn't powerful enough,
there's always "goto label;" where label is either some external label
or the name of one of the cases.  I think I've seen that in C#.  That
also worked well.

So something like this:

final switch( foo )
{
	case 0: goto 1; // emulate the fallthrough
	case 1: writefln("Got a zero or a one.");
	case 2: writefln("This isn't supposed to happen.");
}

I wouldn't complain if it was done some other way though.  Just killing
the fallthrough bugs would make me so much happier.
</rambling and syntax>
July 06, 2009
Chad J wrote:
> Andrei Alexandrescu wrote:
>> Chad J wrote:
>>> These bugs always take me no less than 2 hours to find, unless I am specifically looking for fall-through bugs.
>> I agree. Probably a good option would be to keep on requiring break, but also requiring the user to explicitly specify they want fallthrough in the rare case when they do want it. I'd love to use "continue" for that but it's already "occupied" by cases like while (...) switch (...). Requiring !break or ~break would work but is a bit too cute. Adding a new keyword or a whole new switch statement is too much aggravation. I guess we'll have to live with it...
>>
>>
>> Andrei
> 
> Don't marginalize something that's important!
> 
> The syntax is arbitrary.  Just pick something that works.
> 
> Also, IIRC, the main argument in favor of fallthrough behavior was compatibility with C code.  Now that we have "final switch", we can, with reasonable certainty, assume that no C coder has written "final switch(...) ...".  Thus we are allowed to choose a syntax that's different without breaking anything.  And for those few people that want to write Duff's device, they can just use the old style switch-case.
> 
> <rambling and syntax>
> I'm personally a bit biased to the haXe switch-case statements that I've
> been using for the past few months.  In haXe you don't even have to
> write break; at the end, it will always exit the statement at the end of
> a case-block.  It also has that behavior added in final switch where
> switching on an enum requires you to be exhaustive about your handling
> of the possibilities.  It has worked well.  If it isn't powerful enough,
> there's always "goto label;" where label is either some external label
> or the name of one of the cases.  I think I've seen that in C#.  That
> also worked well.
> 
> So something like this:
> 
> final switch( foo )
> {
> 	case 0: goto 1; // emulate the fallthrough
> 	case 1: writefln("Got a zero or a one.");
> 	case 2: writefln("This isn't supposed to happen.");
> }
> 
> I wouldn't complain if it was done some other way though.  Just killing
> the fallthrough bugs would make me so much happier.
> </rambling and syntax>

Err, forgot to show usage in the example.

auto foo = 0;

final switch( foo )
{
	case 0: goto 1; // emulate the fallthrough
	case 1: writefln("Got a zero or a one.");
	case 2: writefln("This isn't supposed to happen.");
}

// "Got a zero or a one." is printed.
July 06, 2009
Chad J wrote:
> Andrei Alexandrescu wrote:
>> Chad J wrote:
>>> These bugs always take me no less than 2 hours to find, unless I am
>>> specifically looking for fall-through bugs.
>> I agree. Probably a good option would be to keep on requiring break, but
>> also requiring the user to explicitly specify they want fallthrough in
>> the rare case when they do want it. I'd love to use "continue" for that
>> but it's already "occupied" by cases like while (...) switch (...).
>> Requiring !break or ~break would work but is a bit too cute. Adding a
>> new keyword or a whole new switch statement is too much aggravation. I
>> guess we'll have to live with it...
>>
>>
>> Andrei
> 
> Don't marginalize something that's important!
> 
> The syntax is arbitrary.  Just pick something that works.

I've posted here and also sent private message to Walter asking him what he thinks of requiring each case to end with a control flow statement.

> Also, IIRC, the main argument in favor of fallthrough behavior was
> compatibility with C code.  Now that we have "final switch", we can,
> with reasonable certainty, assume that no C coder has written "final
> switch(...) ...".  Thus we are allowed to choose a syntax that's
> different without breaking anything.  And for those few people that want
> to write Duff's device, they can just use the old style switch-case.

That's not the restriction we're having. The C-compatibility restriction is to not have code that compiles in both C and D and has different semantics in the two languages.

So requiring all case-labeled sections in a switch statement to end with a control flow statement would leave some code that compiles in C but not in D. That is acceptable.

> <rambling and syntax>
> I'm personally a bit biased to the haXe switch-case statements that I've
> been using for the past few months.  In haXe you don't even have to
> write break; at the end, it will always exit the statement at the end of
> a case-block.  It also has that behavior added in final switch where
> switching on an enum requires you to be exhaustive about your handling
> of the possibilities.  It has worked well.  If it isn't powerful enough,
> there's always "goto label;" where label is either some external label
> or the name of one of the cases.  I think I've seen that in C#.  That
> also worked well.
> 
> So something like this:
> 
> final switch( foo )
> {
> 	case 0: goto 1; // emulate the fallthrough
> 	case 1: writefln("Got a zero or a one.");
> 	case 2: writefln("This isn't supposed to happen.");
> }
> 
> I wouldn't complain if it was done some other way though.  Just killing
> the fallthrough bugs would make me so much happier.
> </rambling and syntax>

There is a goto case statement in D already. The only change we need to effect is to require it for fall-through code.


Andrei
July 06, 2009
Andrei Alexandrescu wrote:
> [awesome stuff]
> 
> 
> Andrei