back
11 comments
This is really good article on one of the most important things that is not present in mainstream programming languages:

We really need:

1 - expressive switch without default section,

2 - closed enums which aren't just dumb ints

3 - putting more emphasis on compile time safety instead of runtime

We shipped Dart 3.0 last week with support for switch expressions and complex pattern matching in switches. We also managed to get in quite sophisticated exhaustiveness checking.

Whether you consider Dart a "mainstream" language is I guess an open question. :)

The documentation at https://dart.dev/language/patterns is great, thanks
Dart is the DSL for Flutter, right?

(I'll check it out. Thanks for sharing!)

Other way around. Dart is a generic programming language. Flutter is the UI framework built with Dart.

https://dart.dev/

https://flutter.dev/

The joke is Dart is only used with Flutter. It's a language to configure your Flutter application.

It was not a genuine question. The genuine bits were in parentheses.

I can’t tell if you are trying to roast dart or asking a genuine question
Sum types are much more useful with pattern match exhaustiveness checking for sure.
> 1 - expressive switch without default section,

The example the author gives, throwing an error on the default section, is a bit contrived. I agree that exhaustiveness checks should be pushed into the compiler wherever possible and enums are generally less useful than they could be. That said, there are many, many times where you actually want to the use the default section in a switch statement.

Writing in a strongly typed language where you only have to match and handle a few special states out of many would be absolutely abysmal without a default. Even something straightforward like lexing/tokenizing a simple text based structure with things like comments or special metadata would get out of hand quickly. Yeah, syntax can help alleviate that somewhat, but it's still a lot of unnecessary boiler plate. Not to mention it makes the sections much easier to grok at times; "Here we only handle X, Y, and Z differently and we pass everything else along"

> The example the author gives, throwing an error on the default section, is a bit contrived. I agree that exhaustiveness checks should be pushed into the compiler wherever possible and enums are generally less useful than they could be. That said, there are many, many times where you actually want to the use the default section in a switch statement.

It might be worth rereading. Goetz/Bierman are not saying switch defaults are always useless, they are saying that they are often useless. My own experience as a daily Java programmer suggests that the example is not at all contrived - I'm constantly writing switch defaults that will never run.

> Writing in a strongly typed language where you only have to match and handle a few special states out of many would be absolutely abysmal without a default.

Personally, I would much prefer being explicit about which states the code was written to handle, and have the compiler guide me towards asserting that newly added states are valid.

> Because this risk is always present with enums, if an exhaustive enum switch does not have a match-all clause, then the compiler will actually synthesize a default clause that throws an exception. This guarantees that the switch cannot complete normally without selecting one of the clauses.

This is nice. I’ve gotten into the habit of writing such a test after each `switch` statement, for the reasons described (to not disable an exhaustiveness linter warning by presence of a default clause). I just hope they make the exception a RuntimeException (like an IllegalArgumentException) rather than an Error (like a NoSuchMethodError).

However, one disadvantage of the new pattern is that you won’t be able to do your own custom “unexpected enum value” handling any more without also disabling the exhaustiveness check (when implementing it in a match-all clause), because the synthesized check would otherwise preempt it. This is kind of a drawback. There should be an extra syntax for defining a “future case” clause.

Well, if they use a dedicated new exception type, I guess you could catch that, check that it was thrown from the right place (i.e. not thrown from some call within the explicit switch case code), and then do your custom handling. But that would be quite ugly.