August 30, 2001
Oh, I just had a thought.

One of the common mistakes in C is to misspell "default," so that the compiler then considers it a goto label.  Your default case code silently disappears.  Can we make this problem go away?

Maybe by requiring "case default:" rather than just "default".  Maybe use "case else" which is easier to spell, and also returns the word "default" to user-identifier space.  Maybe by *requiring* the compiler to diagnose goto-labels that aren't used.

I dunno, just do something, it's irritating.  Like the forgotten "break" is irritating.

--
Richard Krehbiel, Arlington, VA, USA
rich@kastle.com (work) or krehbiel3@home.com (personal)



August 30, 2001
In article <3B8B80D0.48C7F694@sanger.ac.uk>, "James Gilbert" <jgrg@sanger.ac.uk> wrote:

>  I'd advocate something like:
> 
>     switch (i)
>     {
>         case 1:
>             x = 3;
>             fallthrough;
>         case 2:
>             x = 4;
>         case 3:
>             x = 5;
>     }
> 
> Instead of:
> 
>     switch (i)
>     {
>         case 1:
>             x = 3;
>         case 2:
>             x = 4;
>             break;
>         case 3:
>             x = 5;
>             break;
>     }
> 
> 
Everyone seems to be suggesting having a default behaviour of either break or fallthrough; each of these has problems.  Why not have both break and fallthrough; cases which do not end in one of these should produce a compiler error.  For example:

    switch (i)
    {
        case 1:
            x = 3;
            fallthrough;
        case 2:
            x = 4;
            break;
        case 3:
            x = 5;
            break;
    }

This means that the code is clearer as it is always obvious what will happen.  The fallthrough problem with C is eliminated, without producing a new break problem.  Porting from C or Java to D will therefore be straightforward as you can just put fallthroughs in the places where the compiler complains.


Other suggestions for switch syntax I liked include multiple cases/case
ranges ("case 1..4, 7..10"), and the goto instead of break ("goto case
5").  I also fail to see how these can be combined neatly.

I like the idea of replacing "default" by "else", perhaps in a separate clause like in Pascal:

    switch (i)
    {
        case 1:
            x = 3;
            fallthrough;
        case 2:
            x = 4;
            break;
        case 3:
            x = 5;
            break;
    }
    else
    {
        x = 0;
    }
August 31, 2001
Dan Hursh wrote:

>         switch(c){
>                 case 'a': case 'b': {
>
>                 }
>                 case 'c': case 'd': {
>
>                 }
>         }

If you're going to do this, do it in a more consistent C-style syntax (more like a for or while loop):

switch(c) {
  case('a','b') {

  }
  case('c','d') {

  };
};

Hey - surely D includes labels for continue, as well as break, right?  What about:

switch(c) {
  case('a','b') {

     continue case('f');
  }
  case('f') {

  }
  case('c','d') {

  }
}

Block-style switches also simplify some lookup tables:

switch(c)
{
   case('x') FooX();
   case('y') FooY();
   case('z') FooZ();

   case(default) throw Exception("The character must be one of x,y,z");
}

August 31, 2001
In article <3B8FA4ED.EDED1476@deming-os.org>, "Russ Lewis" <russ@deming-os.org> wrote:


> Hey - surely D includes labels for continue, as well as break, right? What about:
> 
> switch(c) {
>   case('a','b') {
> 
>      continue case('f');
>   }
>   case('f') {
> 
>   }
>   case('c','d') {
> 
>   }
> }

Yes, I like this.  It means you don't have to use a new "fallthrough" keyword and D's syntax becomes more consistent.

> Block-style switches also simplify some lookup tables:
> 
> switch(c)
> {
>    case('x') FooX();
>    case('y') FooY();
>    case('z') FooZ();
> 
>    case(default) throw Exception("The character must be one of x,y,z");
> }

Do you mean that each case is a block (with implied break after each) rather than just a label -- more like in Pascal?
August 31, 2001
In article <3B8DBDCD.E9557EB3@infonet.isl.net>, "Dan Hursh" <hursh@infonet.isl.net> wrote:


> I just had an idea.
> 
> 
> 	switch (c){
> 		case 'a': case 'b':{
> 			// code for 'a' & 'b'
> 		}
> 		case 'c': case 'e':{
> 			// code for 'c' & 'e'
> 			case 'f':{
> 				// cade for 'f', 'c' & 'e'
> 			}
> 			// more code for 'c' & 'e'   **
> 		}
> 		default:{
> 			// code for anything but 'a', 'b', 'c', 'e' & 'f'
> 		}
> 	}
> 
> Thoughts?  Good?  Bad?  Ugly?  Plagiarized?

I think that this is valid in C, except that the case f doesn't break at the end of the block and continues to the ** code.

I think the above code would be somewhat unclear, especially as the interpretation would be different from C's.
August 31, 2001
Ben Cohen wrote:

> > Hey - surely D includes labels for continue, as well as break, right? What about:
> >
> > switch(c) {
> >   case('a','b') {
> >
> >      continue case('f');
> >   }
> >   case('f') {
> >
> >   }
> >   case('c','d') {
> >
> >   }
> > }
>
> Yes, I like this.  It means you don't have to use a new "fallthrough" keyword and D's syntax becomes more consistent.

Moreover, it's enough different from C syntax that it will be obvious to programmers that it's a new syntax.  The argument for/against C-compatibility vanishes if we do it this way.

> > Block-style switches also simplify some lookup tables:
> >
> > switch(c)
> > {
> >    case('x') FooX();
> >    case('y') FooY();
> >    case('z') FooZ();
> >
> >    case(default) throw Exception("The character must be one of x,y,z");
> > }
>
> Do you mean that each case is a block (with implied break after each) rather than just a label -- more like in Pascal?

Yeah, that's the idea.

September 03, 2001

If we were to have (possibly optional) braces
around the switch contents, the compiler could
disallow goto labels outside:

switch (c) {
    case 1: {
        my_label: i++;  // Label allowed inside block
    }
    case 2: {
        j++;
    }
    defau1t: {  /* Bzzzt!
                   Label outside braces;
                   compile error */
        k++;
    }
}

Or maybe disallow goto labels inside switches
all together.  Maybe the switch statement should
look more like the other control structures, and
not use the colon:

switch (c) {
    case (1) {
        my_label: i++;  // Label allowed inside block
    }
    case (2,3,4) {
        j++;
    }
    case (in alpha_num) {   // alpha_num is associative array
        do_stuff(c);
    }
    default {
        k++;
    }
}

I like braces; I feel safe inside them.

	James

Richard Krehbiel wrote:
> 
> Oh, I just had a thought.
> 
> One of the common mistakes in C is to misspell "default," so that the compiler then considers it a goto label.  Your default case code silently disappears.  Can we make this problem go away?
> 
> Maybe by requiring "case default:" rather than just "default".  Maybe use "case else" which is easier to spell, and also returns the word "default" to user-identifier space.  Maybe by *requiring* the compiler to diagnose goto-labels that aren't used.
> 
> I dunno, just do something, it's irritating.  Like the forgotten "break" is irritating.
> 
> --
> Richard Krehbiel, Arlington, VA, USA
> rich@kastle.com (work) or krehbiel3@home.com (personal)
September 03, 2001
Russ Lewis wrote:
> 
> Ben Cohen wrote:
> 
> > > Hey - surely D includes labels for continue, as well as break, right? What about:
> > >
> > > switch(c) {
> > >   case('a','b') {
> > >
> > >      continue case('f');
> > >   }
> > >   case('f') {
> > >
> > >   }
> > >   case('c','d') {
> > >
> > >   }
> > > }
> >
> > Yes, I like this.  It means you don't have to use a new "fallthrough" keyword and D's syntax becomes more consistent.

Oops, should have read this before my last
post.  Yes, I like having it look more like
the other C control structures, and this
eliminates the misspelled "default" silent error.

Do we really need the "continue" if we can
list several alternatives for one case?
There are other control structures that
can be used for complex logic.

switch (c) {
    case ('a','b','c') {
        count_abc++;
    }
    case (2,3,4) {
        count_234++;
    }
    default {
        count_other++;
    }
}


> Moreover, it's enough different from C syntax that it will be obvious to programmers that it's a new syntax.  The argument for/against C-compatibility vanishes if we do it this way.
> 
> > > Block-style switches also simplify some lookup tables:
> > >
> > > switch(c)
> > > {
> > >    case('x') FooX();
> > >    case('y') FooY();
> > >    case('z') FooZ();
> > >
> > >    case(default) throw Exception("The character must be one of x,y,z");
> > > }
> >
> > Do you mean that each case is a block (with implied break after each) rather than just a label -- more like in Pascal?
> 
> Yeah, that's the idea.
September 04, 2001
James Gilbert wrote:

> Russ Lewis wrote:
> >
> > Ben Cohen wrote:
> >
> > > > Hey - surely D includes labels for continue, as well as break, right? What about:
> > > >
> > > > switch(c) {
> > > >   case('a','b') {
> > > >
> > > >      continue case('f');
> > > >   }
> > > >   case('f') {
> > > >
> > > >   }
> > > >   case('c','d') {
> > > >
> > > >   }
> > > > }
> > >
> > > Yes, I like this.  It means you don't have to use a new "fallthrough" keyword and D's syntax becomes more consistent.
>
> Oops, should have read this before my last
> post.  Yes, I like having it look more like
> the other C control structures, and this
> eliminates the misspelled "default" silent error.
>
> Do we really need the "continue" if we can
> list several alternatives for one case?
> There are other control structures that
> can be used for complex logic.

We don't *need* it, but it would be useful.  I often come across things like:

if(a, b, c, or f is true)
{
    if(a)
      doA();
    else if(b)
      doB();
    else if(c)
      doC();

    doABCFCleanup();
}
else if(d or e is true)
{
    if(d)
      doD();

    doDECleanup();
};

So continue isn't necessary, but would be useful.

September 04, 2001
My two cents:

1. I like the idea of required braces instead of breaks. Break must still be permitted so that if statements within a case will work.

2. You don't need a fallthrough keyword if you have goto's. One enhancement might be to make labels inside of switch statements have the scope of the switch itself.

3. The ability to have multiple tests as part of a switch would be great! And you should also be able to test against any type, if possible.

Here's an intentionally-convoluted example of a switch with these features:

  switch ( c ) {
    case 'a': {
      Desired:
      // unique part of this case goes here
      goto AlwaysDo;
    }
    case ('b','c','d'): {
      Acceptable:
      // unique part of this case goes here
      goto Desired;
    }
    case ('e'): {
      // unique part of this case goes here
      AlwaysDo:
      // more stuff
    }
  } else {
    // default case
  }

The compiler should generate an error if a case has no enclosing braces or if no label can be found as the target of a 'goto' statement. Naturally, labels within the scope of the switch statement take precendence over labels with the same name in some outer scope.

PLEASE, whatever you do DON'T use the 'continue' keyword to modify the behavior of a switch; you need continue to behave exactly as in C, because switch statements are legal inside of loops!

  for ( i = 0; i < n; ++i ) {
    <snip>
    switch ( command ) {
      case CMD_SKIPONE: {
        ++i;
        continue;
      }
      <snip other cases>
    }
    <snip>
  }