www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Extend D's switch statement?

reply "Yuxuan Shui" <yshuiv7 gmail.com> writes:
I think it will be useful to extent switch statement to support 
any type that implements opEquals and opHash.

Is there any technical difficulties to implement this?
Jul 08 2015
next sibling parent reply "Martin Nowak" <code dawg.eu> writes:
On Wednesday, 8 July 2015 at 07:15:27 UTC, Yuxuan Shui wrote:
 I think it will be useful to extent switch statement to support 
 any type that implements opEquals and opHash.

 Is there any technical difficulties to implement this?
Hardly anyone wants switch to be a better if-else ladder. https://issues.dlang.org/show_bug.cgi?id=5862 Many would like it to support pattern matching though. http://wiki.dlang.org/DIP32#Various_places_that_you_can_use_unpacking_and_pattern_matching
Jul 08 2015
next sibling parent "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
On Wednesday, 8 July 2015 at 08:31:42 UTC, Martin Nowak wrote:
 On Wednesday, 8 July 2015 at 07:15:27 UTC, Yuxuan Shui wrote:
 I think it will be useful to extent switch statement to 
 support any type that implements opEquals and opHash.

 Is there any technical difficulties to implement this?
Hardly anyone wants switch to be a better if-else ladder. https://issues.dlang.org/show_bug.cgi?id=5862 Many would like it to support pattern matching though. http://wiki.dlang.org/DIP32#Various_places_that_you_can_use_unpacking_and_pattern_matching
I would really like to see tuples become part of the language, maybe with automatic unpacking when they are passed as function args (if the function doesn't explicitly require a tuple in that position).
Jul 08 2015
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/08/2015 10:31 AM, Martin Nowak wrote:
 On Wednesday, 8 July 2015 at 07:15:27 UTC, Yuxuan Shui wrote:
 I think it will be useful to extent switch statement to support any
 type that implements opEquals and opHash.

 Is there any technical difficulties to implement this?
Hardly anyone wants switch to be a better if-else ladder. https://issues.dlang.org/show_bug.cgi?id=5862
I don't think this is what is being asked for. switch(x){ case a: ...; break; case b: ...; break; default: break; } -> switch(x.toHash()){ case a.toHash(): if(x!=a) goto default; ...; break; case b.toHash(): if(x!=b) goto default; ...; break; default: break; } (a and b are known at compile time here, and so are their hash values. Hash collisions between e.g. a and b would need to be dealt with of course.)
Jul 08 2015
parent reply "Yuxuan Shui" <yshuiv7 gmail.com> writes:
On Wednesday, 8 July 2015 at 17:30:59 UTC, Timon Gehr wrote:
 On 07/08/2015 10:31 AM, Martin Nowak wrote:
 On Wednesday, 8 July 2015 at 07:15:27 UTC, Yuxuan Shui wrote:
 [...]
Hardly anyone wants switch to be a better if-else ladder. https://issues.dlang.org/show_bug.cgi?id=5862
I don't think this is what is being asked for. switch(x){ case a: ...; break; case b: ...; break; default: break; } -> switch(x.toHash()){ case a.toHash(): if(x!=a) goto default; ...; break; case b.toHash(): if(x!=b) goto default; ...; break; default: break; } (a and b are known at compile time here, and so are their hash values. Hash collisions between e.g. a and b would need to be dealt with of course.)
Yes, this is what I meant.
Jul 08 2015
parent reply Martin Nowak <code+news.digitalmars dawg.eu> writes:
On 07/08/2015 08:06 PM, Yuxuan Shui wrote:
 switch(x.toHash()){
     case a.toHash():
         if(x!=a) goto default;
         ...;
         break;
     case b.toHash():
         if(x!=b) goto default;
         ...;
         break;
     default: break;
 }

 (a and b are known at compile time here, and so are their hash values.
 Hash collisions between e.g. a and b would need to be dealt with of
 course.)
Yes, this is what I meant.
Very interesting. How would you deal with collisions? You can already do some nice things during compile time, e.g. creating perfect hash functions and lookup table, but it doesn't seem to be possible to achieve what you suggest. Please file an enhancement request in bugzilla (https://issues.dlang.org/) so we don't loose this idea. Keep in mind though that this is mostly syntax sugar for the code above, still requires some specing, has a somewhat uncommon use case, and competes for our limited development time. So don't expect anyone to jump on this, we have a lot of much higher priority stuff to deal with. It would become a lot more useful if you'd find out how to (perfectly?) hash all the case labels to indices of a compact jump table. How are tags of case classes implemented in scala?
Jul 08 2015
next sibling parent "Martin Nowak" <code dawg.eu> writes:
On Wednesday, 8 July 2015 at 21:26:55 UTC, Martin Nowak wrote:
 It would become a lot more useful if you'd find out how to 
 (perfectly?)
 hash all the case labels to indices of a compact jump table.
Apparently called 'Minimal Perfect Hashing'. https://en.wikipedia.org/wiki/Hash_function#Minimal_perfect_hashing Maybe we could also use something similar to speed up druntime's string switching support.
Jul 08 2015
prev sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 09-Jul-2015 00:26, Martin Nowak wrote:
 On 07/08/2015 08:06 PM, Yuxuan Shui wrote:
 switch(x.toHash()){
      case a.toHash():
          if(x!=a) goto default;
          ...;
          break;
      case b.toHash():
          if(x!=b) goto default;
          ...;
          break;
      default: break;
 }

 (a and b are known at compile time here, and so are their hash values.
 Hash collisions between e.g. a and b would need to be dealt with of
 course.)
Yes, this is what I meant.
Very interesting. How would you deal with collisions? You can already do some nice things during compile time, e.g. creating perfect hash functions and lookup table, but it doesn't seem to be possible to achieve what you suggest.
In the worst case just if-else chain collided items per hash value? Given that in this case it may use the full range of size_t I won't expect high collision rates. -- Dmitry Olshansky
Jul 08 2015
parent reply Martin Nowak <code+news.digitalmars dawg.eu> writes:
On 07/09/2015 12:26 AM, Dmitry Olshansky wrote:
 
 In the worst case just if-else chain collided items per hash value?
 Given that in this case it may use the full range of size_t I won't
 expect high collision rates.
There is a readymade tool (gperf) to generate code for perfect hash switches. http://linux.die.net/man/1/gperf
Jul 10 2015
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 10-Jul-2015 16:43, Martin Nowak wrote:
 On 07/09/2015 12:26 AM, Dmitry Olshansky wrote:
 In the worst case just if-else chain collided items per hash value?
 Given that in this case it may use the full range of size_t I won't
 expect high collision rates.
There is a readymade tool (gperf) to generate code for perfect hash switches. http://linux.die.net/man/1/gperf
Does it work for any UDTs? I guess strings only. -- Dmitry Olshansky
Jul 10 2015
prev sibling parent reply "rsw0x" <anonymous anonymous.com> writes:
On Wednesday, 8 July 2015 at 08:31:42 UTC, Martin Nowak wrote:

 Many would like it to support pattern matching though.
 http://wiki.dlang.org/DIP32#Various_places_that_you_can_use_unpacking_and_pattern_matching
all of kenji's proposals are pretty much gold, has there ever been any work on reviewing/implementing this?
Jul 08 2015
next sibling parent "Meta" <jared771 gmail.com> writes:
On Wednesday, 8 July 2015 at 23:33:09 UTC, rsw0x wrote:
 On Wednesday, 8 July 2015 at 08:31:42 UTC, Martin Nowak wrote:

 Many would like it to support pattern matching though.
 http://wiki.dlang.org/DIP32#Various_places_that_you_can_use_unpacking_and_pattern_matching
all of kenji's proposals are pretty much gold, has there ever been any work on reviewing/implementing this?
The tuple syntax was implemented and never pulled. I don't know about pattern matching.
Jul 08 2015
prev sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Wed, 08 Jul 2015 23:33:07 +0000, rsw0x wrote:

 On Wednesday, 8 July 2015 at 08:31:42 UTC, Martin Nowak wrote:
=20
 Many would like it to support pattern matching though.
 http://wiki.dlang.org/
DIP32#Various_places_that_you_can_use_unpacking_and_pattern_matching
=20
 all of kenji's proposals are pretty much gold, has there ever been any
 work on reviewing/implementing this?
at least part of it was implemented by Kenji himsef, and then blocked due=20 to "this isn't a best solution, and if we'll adopt it, we will not able=20 to adopt an ideal solution when it will come". so far, the ideal solution=20 isn't here (and it's unlikely to arrive), and non-ideal is rejected.=20 double win!=
Jul 09 2015
parent reply "rsw0x" <anonymous anonymous.com> writes:
On Thursday, 9 July 2015 at 12:38:11 UTC, ketmar wrote:
 at least part of it was implemented by Kenji himsef, and then 
 blocked due to "this isn't a best solution, and if we'll adopt 
 it, we will not able to adopt an ideal solution when it will 
 come". so far, the ideal solution isn't here (and it's unlikely 
 to arrive), and non-ideal is rejected. double win!
I see this happen a lot, it's always what might be instead of what actually exists and someone was willing to produce.
Jul 09 2015
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/09/2015 02:54 PM, rsw0x wrote:
 On Thursday, 9 July 2015 at 12:38:11 UTC, ketmar wrote:
 at least part of it was implemented by Kenji himsef, and then blocked
 due to "this isn't a best solution, and if we'll adopt it, we will not
 able to adopt an ideal solution when it will come". so far, the ideal
 solution isn't here (and it's unlikely to arrive), and non-ideal is
 rejected. double win!
I see this happen a lot, it's always what might be instead of what actually exists and
I think most of the compiler source code for the ideal solution occurs in at least one of Kenji's rejected pull requests. AFAICS, it's mostly a matter of convincing the guy who wrote std.typecons.Tuple and the guy who does not want to break some (easily replaceable) usages of the comma operator and the identifier "_". :-)
 someone was willing to produce.
Someone is often willing to produce awkward language quirks, so I think being critical of new additions has some value.
Jul 09 2015
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/09/2015 04:17 PM, Timon Gehr wrote:
 On 07/09/2015 02:54 PM, rsw0x wrote:
 ...
 someone was willing to produce.
Someone is often willing to produce awkward language quirks, so I think being critical of new additions has some value.
E.g. "Note: Cannot swap values by tuple assignment. int x = 1, y = 2; {x, y} = {y, x}; // Lowered to: // x = y, y = x; assert(y == 2); assert(x == 2);" No, please.
Jul 09 2015
parent reply "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
On Thursday, 9 July 2015 at 16:08:37 UTC, Timon Gehr wrote:
 On 07/09/2015 04:17 PM, Timon Gehr wrote:
 On 07/09/2015 02:54 PM, rsw0x wrote:
 ...
 someone was willing to produce.
Someone is often willing to produce awkward language quirks, so I think being critical of new additions has some value.
E.g. "Note: Cannot swap values by tuple assignment. int x = 1, y = 2; {x, y} = {y, x}; // Lowered to: // x = y, y = x; assert(y == 2); assert(x == 2);" No, please.
Couldn't this could be detected at compile-time and temporary variables created?
Jul 09 2015
next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Thursday, 9 July 2015 at 22:50:37 UTC, Vlad Levenfeld wrote:
 On Thursday, 9 July 2015 at 16:08:37 UTC, Timon Gehr wrote:
 On 07/09/2015 04:17 PM, Timon Gehr wrote:
 On 07/09/2015 02:54 PM, rsw0x wrote:
 ...
 someone was willing to produce.
Someone is often willing to produce awkward language quirks, so I think being critical of new additions has some value.
E.g. "Note: Cannot swap values by tuple assignment. int x = 1, y = 2; {x, y} = {y, x}; // Lowered to: // x = y, y = x; assert(y == 2); assert(x == 2);" No, please.
Couldn't this could be detected at compile-time and temporary variables created?
Yes, but there needs to be a complete aliasing analysis, e.g. int* x, y; // ... {*x, *y} = {*y, *x}; It's probably safer to create the temporaries by default and elide them when the elements are provably non-aliasing.
Jul 10 2015
parent "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
On Friday, 10 July 2015 at 09:07:21 UTC, Marc Sch├╝tz wrote:
 On Thursday, 9 July 2015 at 22:50:37 UTC, Vlad Levenfeld wrote:
 On Thursday, 9 July 2015 at 16:08:37 UTC, Timon Gehr wrote:
 On 07/09/2015 04:17 PM, Timon Gehr wrote:
 On 07/09/2015 02:54 PM, rsw0x wrote:
 ...
 someone was willing to produce.
Someone is often willing to produce awkward language quirks, so I think being critical of new additions has some value.
E.g. "Note: Cannot swap values by tuple assignment. int x = 1, y = 2; {x, y} = {y, x}; // Lowered to: // x = y, y = x; assert(y == 2); assert(x == 2);" No, please.
Couldn't this could be detected at compile-time and temporary variables created?
Yes, but there needs to be a complete aliasing analysis, e.g. int* x, y; // ... {*x, *y} = {*y, *x}; It's probably safer to create the temporaries by default and elide them when the elements are provably non-aliasing.
Yeah true. I really wish we had this. I've got .tuple and TypeTuple and .expand proliferating throughout the code I write, and I've got a bunch of helper functions for converting between them.... it would be really awesome to get rid of that and unify everything with this DIP32.
Jul 10 2015
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/10/2015 12:50 AM, Vlad Levenfeld wrote:
 On Thursday, 9 July 2015 at 16:08:37 UTC, Timon Gehr wrote:
 On 07/09/2015 04:17 PM, Timon Gehr wrote:
 On 07/09/2015 02:54 PM, rsw0x wrote:
 ...
 someone was willing to produce.
Someone is often willing to produce awkward language quirks, so I think being critical of new additions has some value.
E.g. "Note: Cannot swap values by tuple assignment. int x = 1, y = 2; {x, y} = {y, x}; // Lowered to: // x = y, y = x; assert(y == 2); assert(x == 2);" No, please.
Couldn't this could be detected at compile-time and temporary variables created?
Oh, it certainly is simple to fix, it's just that we don't want this sort of thing to make it into the language specification.
Jul 10 2015
parent reply "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
On Friday, 10 July 2015 at 21:37:10 UTC, Timon Gehr wrote:
 On 07/10/2015 12:50 AM, Vlad Levenfeld wrote:
 On Thursday, 9 July 2015 at 16:08:37 UTC, Timon Gehr wrote:
 On 07/09/2015 04:17 PM, Timon Gehr wrote:
 On 07/09/2015 02:54 PM, rsw0x wrote:
 ...
 someone was willing to produce.
Someone is often willing to produce awkward language quirks, so I think being critical of new additions has some value.
E.g. "Note: Cannot swap values by tuple assignment. int x = 1, y = 2; {x, y} = {y, x}; // Lowered to: // x = y, y = x; assert(y == 2); assert(x == 2);" No, please.
Couldn't this could be detected at compile-time and temporary variables created?
Oh, it certainly is simple to fix, it's just that we don't want this sort of thing to make it into the language specification.
Why not? Tuple handling seems like it should be a 1st class language feature... the disconnect between Tuple and TypeTuple always bothered me on a philosophical (and syntactic) level.
Jul 10 2015
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/11/2015 12:50 AM, Vlad Levenfeld wrote:
 On Friday, 10 July 2015 at 21:37:10 UTC, Timon Gehr wrote:
 On 07/10/2015 12:50 AM, Vlad Levenfeld wrote:
 On Thursday, 9 July 2015 at 16:08:37 UTC, Timon Gehr wrote:
 On 07/09/2015 04:17 PM, Timon Gehr wrote:
 On 07/09/2015 02:54 PM, rsw0x wrote:
 ...
 someone was willing to produce.
Someone is often willing to produce awkward language quirks, so I think being critical of new additions has some value.
E.g. "Note: Cannot swap values by tuple assignment. int x = 1, y = 2; {x, y} = {y, x}; // Lowered to: // x = y, y = x; assert(y == 2); assert(x == 2);" No, please.
Couldn't this could be detected at compile-time and temporary variables created?
Oh, it certainly is simple to fix, it's just that we don't want this sort of thing to make it into the language specification.
Why not? Tuple handling seems like it should be a 1st class language feature... the disconnect between Tuple and TypeTuple always bothered me on a philosophical (and syntactic) level.
..? We don't want the /broken/ thing, which I cited, to make it into the language specification.
Jul 10 2015
parent "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
On Friday, 10 July 2015 at 22:58:44 UTC, Timon Gehr wrote:
 We don't want the /broken/ thing, which I cited, to make it 
 into the language specification.
Ok, I misunderstood. What's broken, if the temporaries are created (and elided following some compiler analysis)?
Jul 10 2015
prev sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Wed, 08 Jul 2015 07:15:25 +0000, Yuxuan Shui wrote:

 I think it will be useful to extent switch statement to support any type
 that implements opEquals and opHash.
=20
 Is there any technical difficulties to implement this?
no, you can do that* with some template programming. so there is no=20 reason to increase compiler complexity. * with some limitations, but they aren't that big.=
Jul 08 2015
next sibling parent "Idan Arye" <GenericNPC gmail.com> writes:
On Wednesday, 8 July 2015 at 09:57:16 UTC, ketmar wrote:
 On Wed, 08 Jul 2015 07:15:25 +0000, Yuxuan Shui wrote:

 I think it will be useful to extent switch statement to 
 support any type that implements opEquals and opHash.
 
 Is there any technical difficulties to implement this?
no, you can do that* with some template programming. so there is no reason to increase compiler complexity. * with some limitations, but they aren't that big.
http://dlang.org/phobos/std_algorithm_comparison.html#.predSwitch
Jul 08 2015
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/08/2015 11:57 AM, ketmar wrote:
 On Wed, 08 Jul 2015 07:15:25 +0000, Yuxuan Shui wrote:

 I think it will be useful to extent switch statement to support any type
 that implements opEquals and opHash.

 Is there any technical difficulties to implement this?
no, you can do that* with some template programming. so there is no reason to increase compiler complexity. * with some limitations, but they aren't that big.
The compiler complexity introduced by this change is trivial. This is completely self-contained.
Jul 08 2015
parent reply Martin Nowak <code+news.digitalmars dawg.eu> writes:
On 07/08/2015 07:33 PM, Timon Gehr wrote:
 
 The compiler complexity introduced by this change is trivial.
Except trivial doesn't mean it's cheap. Would probably take 1-2 days to fully spec/implement/optimize/test/document it. In that time I could finish a thread cache for the GC, or GC-less smart pointers, or finish dub watch, or reduce binary sizes, or finish OSX shared libraries, or join 10 more forum discussions.
 This is completely self-contained.
But is it useful enough to spend the effort and extend the language?
Jul 08 2015
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/08/2015 11:32 PM, Martin Nowak wrote:
 On 07/08/2015 07:33 PM, Timon Gehr wrote:
 The compiler complexity introduced by this change is trivial.
Except trivial doesn't mean it's cheap. Would probably take 1-2 days to fully spec/implement/optimize/test/document it. In that time I could finish a thread cache for the GC, or GC-less smart pointers, or finish dub watch, or reduce binary sizes, or finish OSX shared libraries, or join 10 more forum discussions.
 This is completely self-contained.
But is it useful enough to spend the effort and extend the language?
I just noted that increased compiler complexity is absolutely not a reason not to implement this.
Jul 09 2015