October 30, 2012
On Tue, Oct 30, 2012 at 04:51:33PM -0400, Nick Sabalausky wrote:
> On Tue, 30 Oct 2012 21:39:31 +0100
> deadalnix <deadalnix@gmail.com> wrote:
> 
> > Le 30/10/2012 18:57, Andrej Mitrovic a écrit :
> > > On 10/30/12, Philippe Sigaud<philippe.sigaud@gmail.com>  wrote:
> > >> I've no idea why it's authorized
> > >
> > > There could be a label for a goto there.
> > 
> > That still don't explain what the use case is.
> 
> Obfuscated coding contests?

Is this the official announcement for the inception of the IODCC? ;-) (cf. www.ioccc.org).


T

-- 
Those who've learned LaTeX swear by it. Those who are learning LaTeX swear at it. -- Pete Bleackley
October 30, 2012
Era Scarecrow:

>  Maybe variable declaration (as long as they are default(s))? Has a certain amount of sense, but makes more sense to do it outside the switch case...

Declaring variables there is dangerous:

import std.stdio;
struct Foo {
    int x = 10;
}
void main() {
    int bar;
    switch(bar) {
        Foo f;
        case 10: break;
        default: writeln(f); // prints garbage
    }
}


Bye,
bearophile
October 30, 2012
On Tuesday, 30 October 2012 at 21:40:26 UTC, bearophile wrote:
> Era Scarecrow:
>> Maybe variable declaration (as long as they are default(s))?
> Declaring variables there is dangerous:

>     switch(bar) {
>         Foo f;
>         case 10: break;
>         default: writeln(f); // prints garbage
>     }

 Then it's as though it were '= void;' by default. Most curious. Honestly I'd say it's illegal to have something before any callable case; Besides for goto's it's illegal to jump past declarations, yet this switch case allows it.

 I'd say one of two things must happen then.

  1) Code before the first case is disallowed
  2) Code before the first case always runs

 Option 2 seems silly and unneeded, except it allows a small scope during the switch call, which is it's only possible advantage. The only other advantage is you could have a case disabled and enable it during certain debugging cases, but in those cases why not do the whole block?

>     switch(bar) {
          static if (DEBUG) {
              case -10: /*disabled case, or something like that*/
          }
          Foo f;
>         case 10: break;

October 30, 2012
"deadalnix" <deadalnix@gmail.com> wrote in message news:k6ouhh$116v$1@digitalmars.com...
> Today, I noticed by digging into D details the following construct :
>
> [snip switch being stupid]
>
> What the hell statement is supposed to do ? And what is the use case for this ?

The structure for switch is:
switch(value) Statement(s)

There is very little structure imposed on the statements it contains.  If there are any case or default labels inside the switch that are not inside another inner switch, they are linked to the value and can be jumped to.

One (the only?) use case for the loose definition is Duff's Device.

The reason it's like this in D: that's how it is in C.


October 31, 2012
Some related actual code from a while back:

##################################################
ParseTree prune ( ParseTree p ) {
    p.children = p.children.dup;
    foreach ( ref child ; p.children ) {
        child = prune( child );
    }

    switch ( p.ruleName ) {
        // strip prefix/suffix terminals, then if left with only one child, skip over it
        case "Args"             :
        case "List"             :
        case "Params"           :
        case "Table"            :   p.children = p.children[ 1 .. $ - 1 ];
                                    if ( p.children.length == 1 ) {

        // skip over immediate child (always a "Series")
        case "QualIdent"        :
        case "Type"             :       p.children = p.children[ 0 ].children;
                                    }
                                    break;

        // skip self if it has exactly one child
        case "Addition"         :
        case "BoolAnd"          :
        case "BoolOr"           :
        case "Comparison"       :
        case "Conditional"      :
        case "MaybeParens"      :
        case "Multiplication"   :
        case "Postfix"          :
        case "Primary"          :
        case "Unary"            :   if ( p.children.length == 1 ) {

        // skip self
        case "Expression"       :
        case "Field"            :
        case "Ident"            :
        case "Literal"          :
        case "PathElem"         :
        case "Statement"        :       p = p.children[ 0 ];
                                    }
                                    break;

        default:
    }

    return p;
}
##################################################

Without the loosely defined switch() statement syntax, this would have been a royal pain to piece together.  Especially when each block of cases was evolving over time.

There is also the trick of doing 'switch(val) with(EnumType) {...}' to bring an enum's members into scope so that cases can be written as 'case Foo:' rather than 'case EnumType.Foo:'.

-- Chris Nicholson-Sauls

October 31, 2012
Chris Nicholson-Sauls:

> There is also the trick of doing 'switch(val) with(EnumType) {...}'

What about writing with(EnumType) switch(val) {...} ?

Bye,
bearophile
October 31, 2012
On Wednesday, 31 October 2012 at 22:01:36 UTC, bearophile wrote:
> Chris Nicholson-Sauls:
>
>> There is also the trick of doing 'switch(val) with(EnumType) {...}'
>
> What about writing with(EnumType) switch(val) {...} ?

 Maybe... But a problem arises when it's function wide, and should be able to replace (hopefully) any block. Assuming there's no syntactical issues that may break other code.

int func()
with(EnumType) { //won't compile

}

int func() {
  with(EnumType) { //compiles but seems excessive when it doesn't need to...

  }
}

 But 'switch with' seems the proper way to put it in my mind.
October 31, 2012
Era Scarecrow:

>  But 'switch with' seems the proper way to put it in my mind.

It's not worth the unsafety of the whole switch.

Bye,
bearophile
October 31, 2012
On Wednesday, 31 October 2012 at 22:58:32 UTC, bearophile wrote:
> Era Scarecrow:
>> But 'switch with' seems the proper way to put it in my mind.
>
> It's not worth the unsafety of the whole switch.

 What? I'd need a little explanation what you'd mean. besides, 'switch with' and 'with switch' are practically identical... aren't they?
November 05, 2012
Le 31/10/2012 21:33, Chris Nicholson-Sauls a écrit :
> Some related actual code from a while back:
>
> ##################################################
> ParseTree prune ( ParseTree p ) {
> p.children = p.children.dup;
> foreach ( ref child ; p.children ) {
> child = prune( child );
> }
>
> switch ( p.ruleName ) {
> // strip prefix/suffix terminals, then if left with only one child, skip
> over it
> case "Args" :
> case "List" :
> case "Params" :
> case "Table" : p.children = p.children[ 1 .. $ - 1 ];
> if ( p.children.length == 1 ) {
>
> // skip over immediate child (always a "Series")
> case "QualIdent" :
> case "Type" : p.children = p.children[ 0 ].children;
> }
> break;
>
> // skip self if it has exactly one child
> case "Addition" :
> case "BoolAnd" :
> case "BoolOr" :
> case "Comparison" :
> case "Conditional" :
> case "MaybeParens" :
> case "Multiplication" :
> case "Postfix" :
> case "Primary" :
> case "Unary" : if ( p.children.length == 1 ) {
>
> // skip self
> case "Expression" :
> case "Field" :
> case "Ident" :
> case "Literal" :
> case "PathElem" :
> case "Statement" : p = p.children[ 0 ];
> }
> break;
>
> default:
> }
>
> return p;
> }
> ##################################################
>
> Without the loosely defined switch() statement syntax, this would have
> been a royal pain to piece together. Especially when each block of cases
> was evolving over time.
>
> There is also the trick of doing 'switch(val) with(EnumType) {...}' to
> bring an enum's members into scope so that cases can be written as 'case
> Foo:' rather than 'case EnumType.Foo:'.
>
> -- Chris Nicholson-Sauls
>

Wow this is not actually the case presented in y first post, but still very interesting.