August 04, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 08/03/2013 01:38 PM, bearophile wrote: > enum mysize(T) = T.sizeof; That works... > template Pair(T) = Tuple(T, T); Instead, the following works (alias and !): alias Pair(T) = Tuple!(T, T); Is my change right? Ali |
August 04, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | Ali Çehreli:
> > template Pair(T) = Tuple(T, T);
>
> Instead, the following works (alias and !):
>
> alias Pair(T) = Tuple!(T, T);
>
> Is my change right?
Your change is right, I didn't give enough attention on the code I wrote, sorry :-)
Bye,
bearophile
|
August 04, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On Sunday, 4 August 2013 at 15:38:01 UTC, Dicebot wrote:
> On Sunday, 4 August 2013 at 15:32:17 UTC, monarch_dodra wrote:
>> You pique my interest. What is this? Looks like template shorthand? I didn't find nything about it in docs. Could you share some links about this?
>
> http://wiki.dlang.org/DIP42
Awesome. I'll have to introduce std.traits to this new syntax.
|
August 04, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | monarch_dodra:
> Awesome. I'll have to introduce std.traits to this new syntax.
That DIP is not updated to what was actually implemented by Kenji. There is support for both enum and alias.
But after a good look at my code base I have not found many places where the new syntax is useful. In my opinion it's handy, but it's not a large win. And I still haven't seen any kind of such statistics done on Phobos before the implementation of this feature pair.
People have asked for a more general syntax, useful in more templates, but I have not seen a serious answer that explains why DIP42 is a good idea, while the other more general proposal (of a Self or something to be used in templates to make them more DRY) is is worse.
Bye,
bearophile
|
August 04, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 8/4/2013 11:30 AM, bearophile wrote:
> monarch_dodra:
>
>> Awesome. I'll have to introduce std.traits to this new syntax.
>
> That DIP is not updated to what was actually implemented by Kenji. There is
> support for both enum and alias.
>
> But after a good look at my code base I have not found many places where the new
> syntax is useful. In my opinion it's handy, but it's not a large win. And I
> still haven't seen any kind of such statistics done on Phobos before the
> implementation of this feature pair.
>
> People have asked for a more general syntax, useful in more templates, but I
> have not seen a serious answer that explains why DIP42 is a good idea, while the
> other more general proposal (of a Self or something to be used in templates to
> make them more DRY) is is worse.
I haven't collected statistics, but I see a repeated pattern in Phobos that is addressed by DIP42. It is also consistent with the other eponymous template shortcuts that enjoy wide usage.
|
August 05, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to MattCoder | >> 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. |
August 05, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andre Artus | 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.
|
August 05, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andre Artus | perhaps a more generic solution should be looked at, extend contracts to work with all scope blocks. switch(somenumber) in { ... before stuff ... } out { .... after stuff ... } body { case 1: in { ... etc .... } out { ... more etc ... } body { ... } case 2: // and so on } or perhaps for( int i = 0 ; i < 10 ; i ++ ) in { assert( i == 0 ); } out { assert( i == 9 ); } body { ... stuff ... } if it is desired for a particular contract block to be called in release builds perhaps a attribute label to mark it as a runtime block or something similar. foreach( i, k ; somerange ) @runtime in { ... } body { } |
August 05, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to luminousone | On Monday, 5 August 2013 at 06:28:12 UTC, luminousone wrote: > perhaps a more generic solution should be looked at, extend contracts to work with all scope blocks. > > switch(somenumber) > in { > ... before stuff ... > } > out { > .... after stuff ... > } > body { > case 1: > in { > ... etc .... > } > out { > ... more etc ... > } > body { > ... > } > case 2: > // and so on > } > > or perhaps > > for( int i = 0 ; i < 10 ; i ++ ) > in { > assert( i == 0 ); > } > out { > assert( i == 9 ); > } > body { > ... stuff ... > } > > if it is desired for a particular contract block to be called in release builds perhaps a attribute label to mark it as a runtime block or something similar. > > foreach( i, k ; somerange ) > @runtime in { > ... > } > body { > } Please do not take offense, but I do not see this as a good idea. Contracts have a very different function; not just in D, but every language that uses them. The idea is to support design-by-contract programming. Overloading the constructs for the purposes proposed here would, in my opinion, cause confusion and/or weaken the proper use of contract programming. The code in the contract conditions should never do anything more than what is necessary to specify the contract. It should not do explicit IO (other than implied by assert()), mutate state, or anything like that. At the bottom of this page you can find a reading list for more info. http://www.digitalmars.com/d/dbc.html Or for a general overview: http://en.wikipedia.org/wiki/Design_by_contract Walter, does the D compiler or any of it's companion tools do any static analysis on the contracts? Such as a void safety/null reference check? |
August 05, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to luminousone | Am 05.08.2013 08:28, schrieb luminousone:
> or perhaps
>
> for( int i = 0 ; i < 10 ; i ++ )
> in {
> assert( i == 0 );
> }
> out {
> assert( i == 9 );
> }
> body {
> ... stuff ...
> }
that is just evil code
if you got something todo before or on the first item of the list do it before the loop - and for the last behind the for loop
if we talk about code-duplication then - use an inner function
this type of sub-branching "de-looping" is slow (if performance is relevant) and just not foreach-able, and so not functional-style programming - its called "for loop index micro management for unknown reasons" - but many programmers prefer it very much :)
|
Copyright © 1999-2021 by the D Language Foundation