Thread overview
[Issue 11070] New: Allow auto statement in a switch statement
Sep 19, 2013
Andrej Mitrovic
Sep 19, 2013
Andrej Mitrovic
[Issue 11070] Allow declaration statement in a switch expression
Sep 19, 2013
Andrej Mitrovic
September 19, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11070

           Summary: Allow auto statement in a switch statement
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: andrej.mitrovich@gmail.com


--- Comment #0 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-09-19 10:40:13 PDT ---
Currently if you want to handle an unhandled case in a switch statement you can use a default statement. For example:

-----
import std.string;

auto get() { return "c"; }

void main()
{
    auto res = get();
    switch (res)
    {
        case "a": break;
        case "b": break;
        default:  assert(0, format("Unhandled case: '%s'", res));
    }

    /// res still visible here, we don't want it to be.
}
-----

The problem here is that you're unnecessarily creating the 'res' variable which you will only use for the default statement. Additionally, such a variable shouldn't be visible outside the switch statement if it's only going to be used inside of the switch statement.

I propose we allow an auto statement in the switch statement:

-----
import std.string;

auto get() { return "c"; }

void main()
{
    switch (auto res = get())  // new: allow auto statement
    {
        case "a": break;
        case "b": break;
        default:  assert(0, format("Unhandled case: '%s'", res));
    }
}
-----

This will also eliminate the need for code duplication in switch statements which use a common label statement, for example:

-----
import std.string;
import std.stdio;

auto get() { return "d"; }

void main()
{
    switch (auto res = get())
    {
        case "a": goto common;
        case "b": goto common;
        case "c": goto common;

        common:
            writefln("Got result: %s", res);
            break;

        default:  assert(0, format("Unhandled case: '%s'", res));
    }
}
-----

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 19, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11070


bearophile_hugs@eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bearophile_hugs@eml.cc


--- Comment #1 from bearophile_hugs@eml.cc 2013-09-19 13:16:07 PDT ---
(In reply to comment #0)
> Additionally, such a variable
> shouldn't be visible outside the switch statement if it's only going to be used
> inside of the switch statement.

That's easy solved:

auto get() { return "c"; }

void main() {
    import std.string;

    {
        auto res = get;
        switch (res) {
            case "a": break;
            case "b": break;
            default:  assert(0, format("Unhandled case: '%s'", res));
        }
    }

    // res not visible here.
}



> This will also eliminate the need for code duplication in switch statements which use a common label statement, for example:
> 
> -----
> import std.string;
> import std.stdio;
> 
> auto get() { return "d"; }
> 
> void main()
> {
>     switch (auto res = get())
>     {
>         case "a": goto common;
>         case "b": goto common;
>         case "c": goto common;
> 
>         common:
>             writefln("Got result: %s", res);
>             break;
> 
>         default:  assert(0, format("Unhandled case: '%s'", res));
>     }
> }


Usually common bodies for case statements are not a big problem in D:

auto get() { return "d"; }

void main() {
    import std.stdio, std.string;

    {
        auto res = get;
        switch (res) {
            case "a", "b", "c":
                writefln("Got result: %s", res);
                break;
            default:
                assert(0, format("Unhandled case: '%s'", res));
        }
    }

    // res not visible here.
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 19, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11070



--- Comment #2 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-09-19 13:22:09 PDT ---
(In reply to comment #1)
> That's easy solved.

That's really ugly. It also gets twice as ugly if you have to use a static if.

> Usually common bodies for case statements are not a big problem in D.

Sometimes you have to call specific code for each of these cases, but then follow them with a generic call. So you use a goto to a single label. At the point of the label you won't know what the switch value is unless you stored it somewhere, e.g. (pseudocode):

void main()
{
    switch (auto x = get)
    {
        case "a": handleA(); goto common;
        case "b": handleB(); goto common;
        case "c": handleC(); goto common;
        common: log_output(x); break;

        default:
    }
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 19, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11070


monarchdodra@gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |monarchdodra@gmail.com


--- Comment #3 from monarchdodra@gmail.com 2013-09-19 14:49:31 PDT ---
Well, not just auto, you just want to be able to make a declaration inside the switch expression. This would also apply to a while statement too.

In C++, this is legal:

//----
    while (int i = 1)
    {}

    switch (int i = 1)
    {}
//----

This is a very reduced use case, but I've seen cases where it is useful.

The D grammar does not allow it though. I don't see why not though.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 19, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11070


Andrej Mitrovic <andrej.mitrovich@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|Allow auto statement in a   |Allow declaration statement
                   |switch statement            |in a switch expression


--- Comment #4 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-09-19 15:10:21 PDT ---
(In reply to comment #3)
> Well, not just auto, you just want to be able to make a declaration inside the switch expression.

Yeah, I'll rename the title.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 20, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11070



--- Comment #5 from monarchdodra@gmail.com 2013-09-20 00:53:31 PDT ---
(In reply to comment #3)
> Well, not just auto, you just want to be able to make a declaration inside the switch expression. This would also apply to a while statement too.
> 
> In C++, this is legal:
> 
> //----
>     while (int i = 1)
>     {}
> 
>     switch (int i = 1)
>     {}
> //----
> 
> This is a very reduced use case, but I've seen cases where it is useful.
> 
> The D grammar does not allow it though. I don't see why not though.

To answer my own self:

>     while (int i = 1)
>     {}

This would probably be illegal in D anyways, since we aren't allowed assignments in if/for/while. Arguably, it's not an "assignment" but a "declaration", so it shouldn't be a problem either. Still, it's a thin line, and I have (albeit very rarely) also made that "typo", when copy pasting code.

>     switch (int i = 1)
>     {}

Switch is special, because it doesn't actually test the args, so I see better chances of this being made legal.

IMO, while the use cases arn't very important, not supporting this for switch
would just be a gratuitous deviation from C++ (IMO). Then again, C doesn't
support it either (afaik), so...

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------