Thread overview
bool concat patternmatching with switch
May 28
monkyyy
May 29
Dennis
May 29
monkyyy
May 29
Dennis
May 30
Basile B.
May 30
monkyyy
Jun 04
monkyyy
May 28
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 29

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

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

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:

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 30

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

On Tuesday, 28 May 2024 at 19:39:45 UTC, monkyyy wrote:

>
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...

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

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:

>
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...

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
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
}}
June 04

On Tuesday, 28 May 2024 at 19:39:45 UTC, monkyyy wrote:

>
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 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.)

June 04

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:

>
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 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

June 05

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:

>
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 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:

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.