Hey there, Filip here. This time around, I want to talk about what's new
in Dart 2.15 which was released a few days ago. And again, I love the fact that I'm now no
longer at Google, so I can talk about stuff very freely. It's very liberating. I really
enjoyed the last video about Flutter 2.8. If you have missed it, it's over there
or in the description below or whatever. Now, let's talk about what's new in Dart 2.15.
It's the best kind of update, in my opinion, because there's not much new to learn but your apps will become faster and better
almost for free. Which is fantastic. Okay, so let's have a look at the official blog post by Michael. The biggest
news is making isolates faster. What I really like about isolates in Dart
is that they make things much more sane than if you're using threads and mutex (and
stuff like this) in, for example, Java. The problem with isolates was that they were
pretty heavy and therefore pretty slow, right? In the past, that just meant that you used them
a bit less often. Or, you kind of knew that it's probably not worth it to create an isolate for
this or that. Well, not anymore. Because now... just look: 100 times faster to
start an additional isolate. And you get this for free. When you create, spawn
new isolate, like what you would normally do, it's in an isolate group with the main isolate. And so you get 100 times faster startup,
10 to 100 times less memory. Just amazing. So that's what you get for free.
Also, the isolate doesn't need to deep copy everything. When it sends stuff from
one side to the other, now they've optimized it, and now it's just fast. It's just like, you
know, switching from one isolate to another. This also means that the compute() utility
function... If you're using Flutter, you may know that with compute(), you can very easily
create a new isolate, send it some function, and then make it work on the different
thread. And then just reap the benefits later. Now, compute() is really fast. Before,
when I was at Google, I was like, uh, please don't use compute() a lot because
even if it kind of makes sense at some point, semantically, you just want
to compute something, well, if you're computing something small, then there's
this huge overhead of the isolate. Not anymore! So, yeah, go ahead. I think this is not just making things faster,
it's unlocking new ways to program in Dart. Because things that you were kind of afraid to
use before, and for a good reason (performance), now you can just create 10 new isolates and make
them work. Or create an isolate every second. Why not! Because it's almost free. Also, they're like, in passing, saying: "Oh,
and by the way, just sending medium to small size messages (which is what most isolates
do most of the time) is now 8 times faster." So, yeah. I'm very happy about this. Oh, and you can now send function
types, closures, and stacktrace objects. I actually had a look here. I don't know if
this was possible before. I don't think so. You can just basically... Here, I'm just
sending a function and the data that the function should work on, and then I receive.
And I say what's received, right? And it works. To an extent, this was possible before, I think, because the compute()
function wouldn't work otherwise. But just, like, it's a closure here! It's not
some top-level function. So, this is fantastic. Constructor tear-offs. If you don't know
what tear-offs are, it's just, basically, you tear off the... Let's say, you have
a class, and you have a method in it, and you tear it off. As in, you are just
using the method itself, as an object. One way that I remember it is: you *tear off* the
parens at the end. And then you can just do, like, g(), and run it as a separate function.
So, you're tearing off the method. Well, now you can tear off a constructor. This is
a new syntax that you can use. I don't think that, in this case, this is like the best
use of the new language feature but... I'm pretty sure that especially people building packages and libraries will find this very nice.
I'm not so sure if I want to use it all over the place. But, yeah, it's now possible. Which
also leads to a lot of other stuff like... um, I'll get to this later. I'm going to look at the
CHANGELOG as well, and they go into more details. Enums are now nicer. For one, you can just
do enum.something.name, and it just gives you the String of the enum. In this case, "one".
This was possible before with a terrible hack, because you could do enum.one.toString()...
umm, just terrible. So now, you can do this. You can find a value by name. You can
create a name map, which goes from a string to the enum. So: nice. Nice.
This makes enums a lot more valuable. A new pub retraction feature. Which,
again, is good if you are a developer of a package. But it also is important for
you if you are just using libraries. Now it's possible for you to be using a package
and then, when you update your dependencies, it can tell you, "hey, this package version
has been retracted". This is important because sometimes you have a new version
and this maybe they published the version in error, or there's a big bug there and there
is no resolution yet. So you want to have that [retraction feature]. I'm glad that they added
this feature. But also, it's still the case that if something is published to pub.dev, it stays
there. There's no way to just delete a package from pub.dev. Maybe you followed what happened in,
like, npm and other package managers, where it was possible for someone to just delete something that
everyone else depended on. It's not a good look. And that's it for the blog post
and I also have the changelog. And this is the tear-offs, right? So, if you've
ever seen, or if you've ever had to use a closure that just creates a new instance of something,
then now you just have A.new. Instead of all that. Similar to this, if you have this in
your code, typeOf<something something>, to get a type literal of a generic type, then now
you can just do that. Not a big deal, I think. This one is pretty nice because they basically
found a bug in the null propagation (or whatever they call it). If you check for null, and then
you put it in a variable, and then you check the variable, and then like... for you, of course, now
`i` is not null. Until now, Dart wasn't as clever and it would still throw a compile-time error.
It would tell you that, hey, `i` can be null. Well, it can't, because you just checked
for it [and put it in] a variable. Well now, [Dart]'s clever enough to know it. It's just that you have to have your...
Because this is basically a breaking change, you have to set your minimum SDK to 2.15, and not
lower. So, just do it if that's what you can do. If you have a class and you want the class
to be const, basically, but you still want to keep it kind of open, what's going on, you
can do that now. Before, it wasn't impossible. Async library. Now, unawaited() can get a
null. [The argument] can be nullable. And if it's nullable, obviously, it doesn't
do anything. You can now do foo?.bar(). js_util now has in some cases zero overhead, in calling things and reading properties and
writing them. Which might be really nice for Flutter web projects, and web projects in general.
So, that's just calling from Dart to JavaScript. They removed dart2native, so if you're still
using it, just start using `dart compile exe` or `dart compile aot-snapshot`. Same with
`dartfmt`, which is now `dart format`. There are new fixes and new lint rules
which is always fantastic. We don't talk about it too much, as a community,
but I think lints are fantastic. There's a new flag for if you do pub get, pub
upgrade, pub downgrade, for your `example/` folder. Again, if you have a library,
and you have an example there, then this might make your life easier. So, that is it. Again, I want to say that this is a fantastic
version update of Dart. Because it doesn't add very many new features. I actually think
that's a really really good thing. Because, you don't want a language that adds a new feature
every few months, just because it's cool and someone wants it. Because what you end up with is
a language where there are hundreds of features and it's harder to read. It's harder for
you to understand what other developers are trying to express with their code.
It's just like, sooner or later, things will get messy, you know? I'm looking at
you, C++. (But other languages as well.) Just keeping a balance between, okay, some
new features, but mostly let's keep it boring and let's keep it smooth. That's super
important. And not everyone understands this. I want you, the next time you're thinking,
"oh, this would be so cool, that language has it and Dart doesn't have it", [I want you] to
think about, like, okay, so what about the 99 other things that that language also has, that
would also be cool, but wouldn't that make Dart less fun to use, and less robust, and
everything? One thing that happens a lot in language development, I think, is that the
people who want new features, they will almost always be more vocal than the people who are
just satisfied with what they have currently. The people who are kind of
satisfied are in the majority. But the minority of people who love their
new features will always be more vocal, and for the language designer it then
means that they have to either succumb to this, and add new features, or they have to
be strong enough to be like, "okay, no no no, I know that there are people out there who
are not that vocal about a new feature". So, I want you to be more vocal about this, and be
like: "Hey, do we really need this feature? Do we really like want to throw away simplicity, for the
sake of, you know, maybe saving a few keystrokes?" I don't know. I'm on the side of
the more boring, more predictable, more simple rules for the programming language.
Which make me, I think, more productive in the long run, than a few new features that make
my life a little bit easier here and there. That's it. That was a little rant at the end.
But yes, I'm very happy with the new version of Dart. I hope others are as boring and as
incremental as this one. And see you next time.