www.digitalmars.com         C & C++   DMDScript  

digitalmars.dip.ideas - bool concat patternmatching with switch

reply monkyyy <crazymonkyyy gmail.com> writes:
```d
switch(i%3==0,i%5==0){
   case 1,1: return "fizzbuzz";
   case 0,1: return "buzz";
   case 1,0: return "fizz";
   case ?,?: return i.to!string;
}
```

adding full pattern matching to d seems unlikely to me; but I 
think something should be done to improve ugly if else chains as 
d's switch statements are extremely out of date compared to other 
languages.

I propose syntax sugar where if you pass multible bools (and 
maybe small enums), it will bitshift theses into int and call the 
same basic asm pattern c used for its switch statements.
May 28
next sibling parent reply Dennis <dkorpel gmail.com> writes:
On Tuesday, 28 May 2024 at 19:39:45 UTC, monkyyy wrote:
 I propose syntax sugar where if you pass multible bools (and 
 maybe small enums), it will bitshift theses into int and call 
 the same basic asm pattern c used for its switch statements.
Something like that happens in DMD's source with an `X` function: https://github.com/dlang/dmd/blob/d1f5a7ebd251b3df263a3c6ff87cac4aa9be309c/compiler/src/dmd/e2ir.d#L4770-L4792 You could generalize it up to 64 bits that way.
May 29
next sibling parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Wednesday, 29 May 2024 at 08:59:10 UTC, Dennis wrote:
 On Tuesday, 28 May 2024 at 19:39:45 UTC, monkyyy wrote:
 I propose syntax sugar where if you pass multible bools (and 
 maybe small enums), it will bitshift theses into int and call 
 the same basic asm pattern c used for its switch statements.
Something like that happens in DMD's source with an `X` function: https://github.com/dlang/dmd/blob/d1f5a7ebd251b3df263a3c6ff87cac4aa9be309c/compiler/src/dmd/e2ir.d#L4770-L4792 You could generalize it up to 64 bits that way.
I really dont understand the compilers code, is `X` exposed to a user ever?
May 29
parent Dennis <dkorpel gmail.com> writes:
On Wednesday, 29 May 2024 at 18:41:46 UTC, monkyyy wrote:
 I really dont understand the compilers code, is `X` exposed to 
 a user ever?
It's just a normal function, defined right above the switch statement: ```D static int X(int fty, int tty) { return fty * TMAX + tty; } ``` It combines the two switch variables into a single one with a multiply, the same as your bitshift idea, which is a multiplication by a power of 2.
May 29
prev sibling parent Basile B. <b2.temp gmx.com> writes:
On Wednesday, 29 May 2024 at 08:59:10 UTC, Dennis wrote:
 On Tuesday, 28 May 2024 at 19:39:45 UTC, monkyyy wrote:
 I propose syntax sugar where if you pass multible bools (and 
 maybe small enums), it will bitshift theses into int and call 
 the same basic asm pattern c used for its switch statements.
Something like that happens in DMD's source with an `X` function: https://github.com/dlang/dmd/blob/d1f5a7ebd251b3df263a3c6ff87cac4aa9be309c/compiler/src/dmd/e2ir.d#L4770-L4792 You could generalize it up to 64 bits that way.
It's even a pattern I'd say, there is also this one: https://github.com/dlang/dmd/blob/377613993d35e425dfa43a3cc5cfe4c60acb7607/compiler/src/dmd/dtemplate.d#L1078 In my opinion it would be better to have a builtin "set of enum-member" construct and "set of enum-member"-literals, that are switchable (as essentially they are some integer values). Problems arise when the count of members is > 64 tho.
May 30
prev sibling next sibling parent reply Salih Dincer <salihdb hotmail.com> writes:
On Tuesday, 28 May 2024 at 19:39:45 UTC, monkyyy wrote:
 ```d
 switch(i%3==0,i%5==0){
   case 1,1: return "fizzbuzz";
   case 0,1: return "buzz";
   case 1,0: return "fizz";
   case ?,?: return i.to!string;
 }
 ```
Maybe smarter solutions can be produced with BitFlags. At least it will be more readable... ```d import std.stdio; import std.typecons; enum Status { Idle = 1 << 0, // 0001 Running = 1 << 1, // 0010 Paused = 1 << 2, // 0100 Stopped = 1 << 3 // 1000 } void main() { BitFlags!Status currentStatus; currentStatus = Status.Running; switch (currentStatus) { case Status.Idle: writeln("Durum: Idle"); break; case Status.Running: writeln("Durum: Running"); break; case Status.Paused: writeln("Durum: Paused"); break; case Status.Stopped: writeln("Durum: Stopped"); break; default: writeln("Bilinmeyen durum"); break; } currentStatus = Status.Paused; switch (currentStatus) { case Status.Idle: writeln("Durum: Idle"); break; case Status.Running: writeln("Durum: Running"); break; case Status.Paused: writeln("Durum: Paused"); break; case Status.Stopped: writeln("Durum: Stopped"); break; default: writeln("Bilinmeyen durum"); break; } } ``` SDB 79
May 30
parent monkyyy <crazymonkyyy gmail.com> writes:
On Thursday, 30 May 2024 at 12:56:40 UTC, Salih Dincer wrote:
 On Tuesday, 28 May 2024 at 19:39:45 UTC, monkyyy wrote:
 ```d
 switch(i%3==0,i%5==0){
   case 1,1: return "fizzbuzz";
   case 0,1: return "buzz";
   case 1,0: return "fizz";
   case ?,?: return i.to!string;
 }
 ```
Maybe smarter solutions can be produced with BitFlags. At least it will be more readable... ```d import std.stdio; import std.typecons; enum Status { Idle = 1 << 0, // 0001 Running = 1 << 1, // 0010 Paused = 1 << 2, // 0100 Stopped = 1 << 3 // 1000 } void main() { BitFlags!Status currentStatus; currentStatus = Status.Running; switch (currentStatus) { case Status.Idle: writeln("Durum: Idle"); break; case Status.Running: writeln("Durum: Running"); break; case Status.Paused: writeln("Durum: Paused"); break; case Status.Stopped: writeln("Durum: Stopped"); break; default: writeln("Bilinmeyen durum"); break; } currentStatus = Status.Paused; switch (currentStatus) { case Status.Idle: writeln("Durum: Idle"); break; case Status.Running: writeln("Durum: Running"); break; case Status.Paused: writeln("Durum: Paused"); break; case Status.Stopped: writeln("Durum: Stopped"); break; default: writeln("Bilinmeyen durum"); break; } } ``` SDB 79
your example doesn't show overlapping states and im confused why you set up bitshifting without using it switching over an enum I believe is solved with a `with` block; going with the fizz buzz example, an `enum isfizz{true,false}` wouldnt provide clarity do try to take your example as something that show overlaping states ```d ```d nullable(T){ T me; alias me this; bool isnull=false; } bool isvalid(USERNAME);//looks up a string in a database bool authcheck(PASSWORD,USERNAME);//checks if user/pass match switch(status,username.isnull,username.isvalid,password.isnull,password.authcheck(username){ with(Status){ case Running,0,1,0,1://ideal path case ? ,0,1,0,1://reset server case Running,1,?,?,?://show guest account case ? ,?,?,?,0://invalid password page }} ```
May 30
prev sibling parent reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Tuesday, 28 May 2024 at 19:39:45 UTC, monkyyy wrote:
 ```d
 switch(i%3==0,i%5==0){
   case 1,1: return "fizzbuzz";
   case 0,1: return "buzz";
   case 1,0: return "fizz";
   case ?,?: return i.to!string;
 }
 ```
Two points: You need parens around the case stuff: `case (0,1):` because `case 0,1:` already exists and means `case 0: case 1:`. I filed an [enhancement issue](https://issues.dlang.org/show_bug.cgi?id=24585) for the basic idea. It’s just a lowering that the front-end can do and doesn’t require a DIP. I guess your idea with the `?` is the only part that needs a DIP. (In your example, one could use `default:` though.)
Jun 04
parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Tuesday, 4 June 2024 at 15:55:50 UTC, Quirin Schroll wrote:
 On Tuesday, 28 May 2024 at 19:39:45 UTC, monkyyy wrote:
 ```d
 switch(i%3==0,i%5==0){
   case 1,1: return "fizzbuzz";
   case 0,1: return "buzz";
   case 1,0: return "fizz";
   case ?,?: return i.to!string;
 }
 ```
Two points: You need parens around the case stuff: `case (0,1):` because `case 0,1:` already exists and means `case 0: case 1:`. I filed an [enhancement issue](https://issues.dlang.org/show_bug.cgi?id=24585) for the basic idea. It’s just a lowering that the front-end can do and doesn’t require a DIP. I guess your idea with the `?` is the only part that needs a DIP. (In your example, one could use `default:` though.)
I kinda doubt its a mere enhancment, d has the dumb c style switches that are thin abstractions of goto; this will require a preprocessing step that im unsure if it exists at all currently
Jun 04
parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Tuesday, 4 June 2024 at 20:08:13 UTC, monkyyy wrote:
 On Tuesday, 4 June 2024 at 15:55:50 UTC, Quirin Schroll wrote:
 On Tuesday, 28 May 2024 at 19:39:45 UTC, monkyyy wrote:
 ```d
 switch(i%3==0,i%5==0){
   case 1,1: return "fizzbuzz";
   case 0,1: return "buzz";
   case 1,0: return "fizz";
   case ?,?: return i.to!string;
 }
 ```
Two points: You need parens around the case stuff: `case (0,1):` because `case 0,1:` already exists and means `case 0: case 1:`. I filed an [enhancement issue](https://issues.dlang.org/show_bug.cgi?id=24585) for the basic idea. It’s just a lowering that the front-end can do and doesn’t require a DIP. I guess your idea with the `?` is the only part that needs a DIP. (In your example, one could use `default:` though.)
I kinda doubt its a mere enhancment, d has the dumb c style switches that are thin abstractions of goto; this will require a preprocessing step that im unsure if it exists at all currently
Your `switch` could be: ```d switch (((i%3==0) << 1) | (i%5==0)) { case (1 << 1) | 1: return "fizzbuzz"; case (0 << 1) | 1: return "buzz"; case (1 << 1) | 0: return "fizz"; default: return i.to!string; } ``` The transformation is mechanical and absolutely trivial, and it’s the same “dumb C-style switch” it has always been. For string switching, something more nuanced is needed, but string switches are special anyway.
Jun 05