Improvements to switch

Meta jared771 at gmail.com
Fri Apr 19 19:27:22 UTC 2024


On Friday, 19 April 2024 at 07:40:34 UTC, Nick Treleaven wrote:
> On Friday, 19 April 2024 at 06:28:55 UTC, Meta wrote:
>> On Wednesday, 17 April 2024 at 11:24:16 UTC, Nick Treleaven 
>> wrote:
>>> On Tuesday, 16 April 2024 at 18:25:45 UTC, Meta wrote:
>>>> - branch guards
>>>> - pattern match on arrays, slices:
>>>
>>> Some other things, based on section 3.3 of this C++ proposal:
>>> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2392r2.pdf
>>>
>>> - Multiple alternatives that have the same result: ||
>>>
>>> E.g.
>>> ```d
>>> case :9 || :15 -> "not prime";
>>> ```
>>
>> This is already covered by regular switch statements. You can 
>> write:
>> ```D
>> case 9, 15 -> "not prime";
>> ```
>
> It would be ambiguous to write e.g. `case name if (cond) ->` - 
> is it matching a value `name`, or is `name` naming the switch 
> variable?

I'm not quite sure what you mean - can you illustrate in more 
detail?


> But the grammar was me trying to extrapolate from your 
> examples, and it might not be workable for that to be 
> compatible with today's switch statement. Perhaps it's better 
> to not reuse `switch` because we will want pattern matching 
> with multiple statement branches, we won't always want `switch` 
> to be an expression.

Yeah maybe not. That was just some mock syntax off the top of my 
head, and it's probably not suitable for extracting a formal 
grammar.

>>> - Grouping common names and constraints: { }
>>>
>>> E.g.
>>> ```d
>>> switch (variant) {
>>>     case int i {
>>>         case if (i < 0) -> "negative int";
>>>         default -> "some other int";
>>>     }
>>> ```
>>
>> ```D
>> switch (variant) {
>>     // goto default is already a feature of regular switch 
>> statements
>>     case int i -> i < 0 ? "negative int" : goto default;
>>     default -> "some other int";
>> }
>> ```
>> This will work _if_ `goto default` is typed as `noreturn`. I 
>> doubt that's the case, but that's something that can also be 
>> fixed in the compiler.
>
> BTW that's not what my example does - the `i < 0` is part of 
> the matching, not part of the result. The difference is there 
> can be other `case` statements under the first one. `case if (i 
> < 0) ->` would try the next case statement when i >= 0 rather 
> than jumping to the default case.

I see. I think having nested case conditions might make it too 
complex to understand and maybe even implement.

> Also for your example I don't understand why `goto default` 
> wouldn't have the same type as the result for the `default` 
> branch.

Conceptually, `goto default` and other constructs that transfer 
execution to a different part of the code should be typed as 
`noreturn`, because then you can do stuff like:

```D
auto input = readln() || throw new Exception("empty input");
```

Although in this case it would actually be pretty weird... I 
_think_ it would enable this type of code:

```D
Variant v = 10;
auto str = switch (variant) {
     case int i -> i < 0 ? "negative int" : goto default;
     default -> writeln("invalid value");
};

// The only sane type for `str` is `noreturn`, and thus it should 
crash the program if we try to read from it.
```


More information about the dip.ideas mailing list