Kotlin Things I Miss In Dart, Part 1

Starting in 2021 Dart replaced Kotlin as my favorite language. In the backlog of post ideas for my blog I had a whole bunch of language comparison ideas but haven’t written any of them yet. As I was cranking through some Dart code this week though I was thinking more and more about this. Dart as a language is still evolving. In the Dart 3 alpha notice they talk about some really neat things coming in future versions. With all that there are some Kotlin features big and small that I wish would be added to some future versions. This is the first but probably not the last of these posts, hence the “part 1”, where I figured I’d document it.

Underscore Separators in Numbers

It seems like a very minor thing, but when working with larger numbers it is convenient to have a way to mark off every thousands element. In the US we usually use commas for this but commas already have their purposes. So too do periods/dots. In Kotlin they allow the use of underscores when defining number constants. Dart doesn’t have that sort of capability. This week when I was operating with very large numbers it would have made proofreading it so much easier:

val x = 1000;
val y = 1_000_000;
val z = 1_000_000.35;

versus:

final x = 1000;
final y = 1000000;
final z = 1000000.35;

If-Then and Switches Returning Values

There are many cases where we need to use some logic in determining the value of a variables. In the days before we wanted things to be as immutable as possible we would do something like:

int x;

if (getSomeSetting() == GOOD_VALUE) {
    x = 0;
} else {
    x = -1;
}

We even invented a compact syntax for this called the “ternier operator” which allowed for combining it all into one line and setting the value:

int x = getSomeSetting() == GOOD_VALUE ? 0 : -1;

This sort of thing is even more valued in the modern era where we want to generally keep variables immutable. This switch to immutability helps both with reducing introduced bugs as well as can help with compiler optimization. However what happens when you have to do something like the first case, where the ternary operator doesn’t make sense? In Dart it introduced the concept of the late keyword. Using this with final you can tell the compiler that this variable will be written to later but only once.

late final int x;
if (getSomeSetting() == goodValue) {
    x = 0;
} else {
    x = -1;
}

If you try to read x before it is assigned the compiler will detect it if it can. Worst case you get a run time error. The same is true if you try to set the value a second time. Kotlin got around it by letting the results of if and switch statements return values themselves. This introduces a whole new class of code flexibility which can come in handy later.

val x = if (getSomeSetting() == goodValue) {
    0;
} else {
    -1;
}

It gains even more power when used with switch statements:

val x = when(getSomeSetting()) {
    goodValue -> 0
    someOtherValue -> 1
    else -> -1
}

I’d love to see both of these concepts added to Dart. I’m pretty sure the underscores one would be pretty simple. The whole changing ifs/switchs to return values is probably a much more dramatic change which makes doing so difficult to impossible.

UPDATE: As it turns out “switch expressions” will be in the next version of Dart after all! (Link)[https://mokshmahajan.hashnode.dev/unlock-the-magic-of-pattern-matching-in-dart-30#heading-switch-expressions]