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.