On Monday, 5 August 2013 at 04:07:55 UTC, Andre Artus wrote:

Andre Artus:
int number;
string message;
switch (number)
{
        default: // valid: ends with 'throw'
                throw new Exception("unknown number");
        case 3:
                message ~= "three "; break;
        case 4:
                message ~= "four "; continue;
        case 5:
                message ~= "five "; goto case;
        case 6:
                message ~= "six "; break;
        case 1:
        case 2:
                message = "one or two";
}

With the inclusion of 'default' the condition covers the whole range of 'int'. The programmer may only want the pre and post code to be executed for every other case (1..6).

MattCoder:
Like I said, it would be nice if we could extend some D features without change the compiler source, maybe like macros in LISP.

It may not always be the case, but in my experience this often leads to write-only code. I'm pretty new to D, so I'm not quite up to speed with the metaprogramming abilities, but I'm under the impression that this is what mixin's are for.

MattCoder:
The switch statement should have an event handler like: onBeforeMatch or onAfterMatch to handle this.

But for what I saw on this thread, this is only possible changing the compiler source. :/

Matheus.

In order to produce the most sane (in my opinion) construct the code cannot be rewritten as JS suggested:

JS:

if (cond) { <common_body1> }
switch (cond)
{
   case <symbol> : <case body> [break or return or fallthrough]
   ...
   <default> : <default_body>  [break or return or fallthrough]
}
if (cond) { <common_body2> }
if (!cond) { <else_body> }

As I mentioned before `switch` takes an expression that evaluates to integral or char[], the condition is completed in the `case`. The condition leading to the 'common' entry and exit code must replicate that of the complete switch statement. This begs the question about how to handle `default`. It would be difficult to correctly reason about the code without additional information.

The only suggestion that leads to sane results in all (maybe?) cases is that made by Ary Borenszweig.

Ary Borenszweig:

switch(cond) {
 case A:
   common_code();
   // something
 case B:
   common_code();
   // something else
}

I would think that the common code could be factored into a function taking a void delegate (analogous to C# Action<T> delegate) then passing the case specific code as a lambda. This is something I have done in C#, but not yet in D.

In C# you would something like this:

private void UseAGoodNameDescribingCommonCode(Action action)
{
    // Entry code
    action();
    // Exit code
}

switch(expression) {
  case A:
        UseAGoodNameDescribingCommonCode(() => {
            // something        
        });
        break;
  case B:
        UseAGoodNameDescribingCommonCode(() => {
            // something        
        });
        break;
  default:
        // Something else
}

It's very clear where it's being applied, and where it is not.

If the compiler was rewriting the following:

switch(expression) {
common_entry: // should not be order specific i.e. overloading 'common'
                // entry code
                break;
        common_exit:
                // exit code
                break;
        case A:
                // something
                break;
        case B:
                // something else
                break;
        default:
                // default something
}

It could produce something like this:


switch(expression) {
common_entry: // should not be order specific i.e. overloading 'common'
                // entry code
                goto pop_label();
        common_exit:
                // exit code
                break;
        case A:
// could set var or register used push/pop for clarity of intent
                push_label(A_prime);
                goto case common_entry;
        label A_prime:
                // something
                goto case common_exit;
                // break not needed here;
        case B:
                // rinse & repeat
        label B_prime:
                // rinse & repeat
        default:
                // default something
}
What to do with default needs to be disambiguated.

I should point out that 'common_entry' and 'common_exit' are not really cases, but labels as they are not explicitly tied to the input expression.

Reply via email to