[MUSIC PLAYING] BOB NYSTROM: Are you guys ready? [APPLAUSE] Yes? Yes? KEVIN MOORE: That it? All right. My name is Kevin Moore. I'm a product manager
on the Dart team. BOB NYSTROM: I'm Bob Nystrom. I'm a software engineer
on the Dart team. KEVIN MOORE: And today. We've got lot of to go through. We'll try not to go too fast. Here's the rundown. We're going to talk about the
three things in the title. What we love about Dart. Why we think Dart is cool. We'll talk about the language. We'll talk about the platform. And we'll talk about some
of the future directions we're going with Dart. Sound good? So Dart-- BOB NYSTROM: If
you don't like it, we can do something different. KEVIN MOORE: Anything else? No, that sounds good? OK, we'll stick with that. That's what we practiced. It's probably a good idea. So Dart's a
programming language. It has a platform, a runtime,
compilers, all those things, right. We're all on the
same page there. If you've heard of Dart,
you've probably heard about it in the context of Flutter. Right? Some people here. Occasionally, we
get the question. Why did Flutter choose Dart? Sometimes it's done
very politely and just with genuine curiosity. BOB NYSTROM: Always. KEVIN MOORE: I
don't know always. There was that one Perl
guy once like, why not. So, as a way to jump
in, I think that's a good way to talk about,
why did Flutter choose Dart. What's cool about Dart. So if you don't know
already, Flutter is a framework for building
beautiful applications. They run across mobile
devices and other things. We'll talk about that in a bit. Here's some examples. If you look at the
Flutter architecture, on the lowest level
is a C++ engine. Flutter doesn't use the
native UI stack or widget library on IOS or Android. It has its own. And it runs on its own runtime. Skia is part of that. That's the engine that
drives Chrome as well. The Dart VM is buried
in there as well. As long as some tech support. And then the whole
Flutter framework is all written in Dart. So everything from the
lowest level foundation bits, the core animation things,
routing, the widgets, theming, rendering. That's all written in Dart. Then of course, the bulk of the
Flutter application you write is also in Dart code. So you have your
app, the framework, and then even in the C++
engine, you have Dart. So clearly Flutter has made
a big investment in Dart. It's not just a
scripting layer on top. So we want to talk
about these three things that we think are important to
Flutter and important to Dart. Productivity. We want you to be able to
be productive and happy as a developer and get
things done quickly. We want you to be fast,
and this means two things. We want your productivity to be
fast to be able to get things done quickly. And then you ship your app,
we want it to be amazing-- 60 FPS, high quality, fast. And then we want to
run on many platforms. Now, this is a hard
set of three things. It's pretty audacious
to try to do this. We think we have a
pretty good story, and so that's what we're
going to talk about. BOB NYSTROM: Oh, I
get the clicker now. So, we're going to start
talking about productivity. So, the primary domain,
the application style that we're aiming for with Dart,
is building user interfaces. So client application
development. And for that domain
in particular, developer productivity
matters a ton because a lot of what
you're doing is very small scale subjective
changes-- tweaking UI, layout, color stuff. So you want that
really fast loop so that you can get to
a good user experience. Productivity starts
with the language that you're programming in,
which, spoiler alert, is Dart. I'm assuming that you
haven't seen Dart, so I will run through things. But I obviously
don't have time to do a deep dive or a full
intro with the language. So I'm going to
kind of skim stuff. If stuff doesn't
sink in, that's OK. I just want to paint a
picture in your mind. I think of Dart as being
a modern, multi-paradigm language. And it's been designed to be
familiar to people coming from other mainstream languages,
JavaScript, Java C#, things like that. Curly Braces, that
kind of stuff. It's in the same family,
the same ballpark as Kotlin and Swift. So by modern, what I mean is
that it's kind of lightweight, it feels a little scripty. So here's a slightly more
elaborate Hello, World program. We've got collection literals. There's string interpolation. You don't have to
define a class to make a new file, things like that. But it's not just a
scripting language. It is also an
object-oriented language. So we have classes, objects,
methods, fields, interfaces, all that good stuff. We have some interesting
object-oriented features like mix-ins. I don't have time to talk about. Object-oriented
programming, people have strong feelings about it,
some of which are positive, some of which are negative. I'm sympathetic
to both of those. My personal experience-- I've
been doing UI programming for a long time-- is that for UI stuff in
general, in particular, OOP is just a really nice fit
for it, works really well. So this is the
domain we care about. So we have these
features, and I find it as my program gets
larger, these features help me organize the
larger structure of it. But Dart is not dogmatic about
object-oriented programming. Because we are a
modern language, we also support a
functional style. So we have lambdas. Here are the little arrows
making a function here. We have closures. If you see, the bang is
declared outside of it. We have higher order methods. So here, we're passing a
closure to the map function to transform it. All this stuff is
familiar to you now. If I was giving this
talk 10 years ago, people would be like, I've
never seen any of this, unless you're a
scheme programmer. And the neat thing is, this is
deeply baked into the language in the core library. So I'm calling map right
on the built-in list type. So all this stuff, the
functional style that you like is all baked in. But a language is more than
just its runtime semantics. So we take that behavior
and we wrap all that up in a nice static type system. So, you can do the typical
things that you expect. You can put type
arguments on [? your-- ?] type annotations on your
parameters, return types. And then the type
checker will tell you if you made mistakes, because
we are human, and we do that. This is another
thing where people have strong feelings about it. My personal experience
is that when my code is small, when my
programs are small, types-- sometimes they get in the way. Sometimes they're net-neutral. But as my program grows, or
as I work on larger teams, I really appreciate having
the structure and the kind of defenses that
static types give me between the different
regions of my code. We have this idea that we want
users to never outgrow Dart. Your program should
never get so large that you feel like, well,
Dart can't handle it, and I need to port it
to another language. And static types are
a big part of that. When I say that we have a modern
static type system, what I mean is things like this. So we have generic classes. So here, this is
declaring a box of T that has a field of type T. So
a box of int and a box of string are different types. I'm using a weird,
contrived example here. I know you're looking at
this, and you're like, this is not adding
any value to my life. Hopefully it will be. I'll walk you through why
I picked this example, and hopefully it will
make a little more sense. KEVIN MOORE: It's
a tuple of one. It makes total sense. BOB NYSTROM: Yeah, exactly. Thank you. KEVIN MOORE: There you go. BOB NYSTROM: We also
have generic methods. So here, this method rebox
has its own type argument R, which is different from
the surrounding classes type argument. And it takes a function,
takes a first class function as a callback, and invokes that
callback on its own contents. Gets a new object back,
wraps it up in a new box. So this will turn a box
of T into a box of R. Obviously, super useful. This is something you
want to do every day. Here's why I'm actually
talking about this. So, static types are nice. The safety you get
from them is nice, but having to write
code like this is slightly less nice, right. It's cool that it's typed,
but it's pretty verbose. So we also have a
rich type inference system on top of this. So I'll walk you
through what you can do. So, when you're constructing
a box of string here, well, we can tell you're
passing it as string. So it must be a box of strings. You don't have to write that. Inference will fill that in. When you're declaring
this string box variable, we can see that
you're initializing it with a box of string, so we
can infer that, obviously. You see here when
you call rebox, you're passing num.parse. That's a core library
function that returns a num, so we know that
that's rebox of num. And then we know the
return type of that method, so we know what the variables
type is going to be. And then we know
that's a box of num, so we know its contents type. So, actually, we
can infer that, too. So this is what idiomatic
Dart looks like. And the nice thing is that this
is fully, statically typed, just like the previous code. You get all the safety
that you had before. You get all the code
navigation, all that good stuff. KEVIN MOORE: So, that
means if I go and I said, print string box, that
runtime type, I would see, box of string. BOB NYSTROM: Yes. Yeah, the actual type
it constructs at runtime is correct, too. Our goal here is to give
you basically the brevity of the scripting
language, but then the safety of a
statically typed language. So this is my super
science summary of the language
I'll run through. So, we try to be lightweight
and feel modern scripty. We give you, when
you're organizing your code, the
structure you like from object-oriented
programming. And then inside your
methods and stuff, we give you that nice
declarative style that you get from
functional programming. And then we kind of wrap that
up in a nice, rich static type system that can understand
both of those paradigms. So this is a foundation of
a general purpose language. And Dart is a good
general purpose language. But we want it to
be particularly good for writing
client application, for writing UI code. So over the past
year, we've been working on this
initiative called UI is code, where
we've tried to add a few features to
the language to make it even better for that--
that use case and other stuff. So I'll walk through
it a little bit. I'll show you an example
of what you would do now. And then we'll go back and
see how the new features work. So if you haven't
seen it before, this is what a little contrived
bit of Flutter code looks like. So anytime you build
your new UI framework, you have to figure
out how the users are going to author their UI. Sometimes they say that you do
it in a separate template file. Sometimes you embed the
templates in the code. For Flutter, you just do
it using vanilla Dart code. So your UI code is Dart code. What's nice about
that is, you don't have mental context
switching when you're moving between the code and the UI. There's only one
language to learn. All of the features from the
Dart language that you like, you can use in your UI. So this is kind of a
simple, trivial example. And it looks pretty nice, right. Like the body of that method
is just a single expression, which is why we can
use a little arrow. And it's just a
nice little widget tree that just builds a column
with a series of text elements. You can imagine we're building
maybe the navigation for a book reader or something. This is the goal. This is what we want
your code to look like, and this is hopefully
what you feel-- you feel good about your
code when it looks like this. So let's start making it
a little more interesting. So let's say that when you're
on the last page of the book, we don't want to
show the next link. So, what do you need
to do to get to that? So first of all,
we're going to have to do a little bit
of imperative logic. So now it's not going to
have an expression body. We're going to need a block. And actually, we need to
do something like this. So we pull that
list literal out, we hoist that up to
a local variable, then we need an if statement to
imperatively add the next link. And we even need to
imperatively add the index link to the end of that,
even though that's not doing any interesting
logic, just because it happens to appear later. So we had a sort of
small conceptual change, but it required a very
large code change. So let's keep going. So let's say, also
what we want to do, is we want to add links
for every section. So that's another little
bit of imperative code. Here we're using
add all, because we want to take that sections list
and unpack it into the list that we're building
here for the column. This is OK. Again, this is an
imperative code, so it's not the
end of the world. We'll keep going
a little bit more. So let's say actually
what we want to do is, for every section, we want
to include all of its chapters. So we flatten out the
sections and include each of the chapters. And this is what you get. So I think most people
can read this code. It's not the end of the world. KEVIN MOORE: But I have to
run the compiler in my brain. BOB NYSTROM: Right, but yeah. To think about what is the
UI structure this generates, you basically have to
execute it in your head. The textual structure the
code doesn't reflect your UI structure anymore. So, let's go ahead
and rewind it. I did a little rewind
transition there. I'm very excited about that. KEVIN MOORE: So the
return method's gone. We're back to a nice
arrow, which is-- BOB NYSTROM: We're starting
back at the very beginnings. So, the first thing we wanted
to do, and this is with the new features that we're adding now. The first thing we wanted to
do was omit the Next button when you're on the last page. So for that, we just
let you stick an if right inside the list literal. It does, hopefully,
what you can infer. So if that condition
is true, the body gets inserted in that element
in the list, condition's false, doesn't insert anything. So notice the body, that
it's not saying add text. There's nothing imperative here. It is just the
expression for the thing that goes in the list. OK, so what do we
want to do next? The section links. So for that, this
little dot dot dot here is called a spread operator. It's something we
borrowed from JavaScript. So when you use this inside
a collection literal, it takes the
sequence following it and it unpacks it in place
in the surrounding list. The last thing we did was
we walked [? through the ?] sections and then
did the chapters. So for that, we also
let you do for directly inside a collection literal. So what this will do is,
just like a for-loop, it will execute that
body multiple times. And that body can
produce as many elements as it wants each
time, and all of those will then get flattened out
into the resulting collection. So the super science
summary, this is kind of the before
and after here. So these features. These are three
relatively small features. They're kind of incremental
additions to the language. I didn't show
examples here, but all of these work with all of
the collection types in Dart. So we have map literals
and set literals, too. And you can use these and those. They can also be
freely composed. Here you can see we're
using a spread inside a for. But these are not amazing
rocket science features, right. But what I like about this is
it gets the code 30% smaller. What I really like is that the
code stays more declarative. And at every step
of this when we needed to introduce
a little logic, we never had to go back
and rewrite our code in an entirely different style. So any small conceptual
change we made was a small textual change. That almost rhymes. That's great. So-- KEVIN MOORE: I'm
tweeting that later. BOB NYSTROM: So this is
the new stuff we have. This came out in Dart
2.3, which was released-- KEVIN MOORE: Today. BOB NYSTROM: Like right now. KEVIN MOORE: Yeah. BOB NYSTROM: And
in Flutter 1.5-- KEVIN MOORE: Yes. [APPLAUSE] It's cool stuff, right. Yeah, that's pretty cool. Bob did a big part in
implementing this stuff. So good job, Bob. BOB NYSTROM: These
are my babies-- my three strange little
syntactic babies. So this is the
language, but this is kind of the language spec. A language is more than
just a paper specification. KEVIN MOORE: I've heard. You're right on time. That was amazing. Wow. So that's the language. Now languages are great, and
they're great to discuss, but at some point you want
to run the code, right? I guess there probably are
people who put in a text file and just share it. BOB NYSTROM: I just read specs. KEVIN MOORE: Yeah, exactly. Then I write, so it's perfect. So how do we run code in Dart? So we start. Anyone who's taking the compiler
class, which I never did. I've learned it all
on the Dart team. BOB NYSTROM: It's
never too late. KEVIN MOORE: I know,
you help me a lot. So you start with a text
file, Dart source code, and you Lexer + Parser
it, and you get an AST. Yes. BOB NYSTROM: Yes,
I got that right. KEVIN MOORE: Stands for
Abstract Symbol Tree? BOB NYSTROM: So close. KEVIN MOORE: Arbitrary Sync? BOB NYSTROM: You're
getting farther. Colder, colder. KEVIN MOORE: Abstract. BOB NYSTROM: No. Yes. KEVIN MOORE: Symbol. BOB NYSTROM: Syntax. KEVIN MOORE: Syntax tree. There we go. BOB NYSTROM: Ladies and
gentlemen, Kevin Moore. [APPLAUSE] KEVIN MOORE:
Understood continue. So on top of that,
when we're thinking about running Dart code, we have
this amazing little compiler. And it does things
that compilers do. So Bob showed the type inference
stuff, does all that logic. Type checking. We make sure things
are accurate. Evaluating constants,
optimizations, collapsing constants. So if you define 15 strings,
const, const, const, and then you have some 16 string
that's like, I want all these, plus, plus, plus,
plus, when we compile, we'll just generate
one string for you. We can do all that
kind of logic. And then we have back-ends
that run your code. And we'll talk about
that in a little bit. On the side here, we
have a separate stack, and these are the
bits that actually enable a dev experience. So we have a package
called Analyzer. And the idea is,
you want to stack a code on the left,
the yellow bits, that can take correct code and
deal with it really quickly. Go as fast as you can from
Dart source to something we call kernel. Talk about that more later. On the right side, you want a
separate set of stuff that's really good at incomplete code. Because I don't know about you,
but at some point I'm typing, and my expressions not
complete, and I want to hit Tab and get completion. And so, those are
the analyzer bits, and so all the things you
think about a dev experience are handled there. This is also a package,
which is super exciting. So if you want to write
code that looks at Dart code and generates Dart code,
something I'm very fond of, you can use that. On top of that,
we build a server that runs in your
local machine, that basically knows how
to take those bits and expose it to clients-- so your IDs. So when you think of the
green bits, this is it. So if you're-- go to
definitions, refactor, find using, all those
things, the red squiggles. That's the stuff in green. That's the analysis bits. But the yellow bits, we
talk about running code. And so we think about
fast, and I actually think of fast in two contexts. One is your dev cycle. So this is how
quickly you can go from changing a line of
code, changing a bit of code, and seeing it running,
seeing if it works or not. So that's enabled
by the Dart VM. So all those yellow
bits are there in the yellow box,
the CFE, and then we have all these things on top. And so the CFE basically
takes your source code and gives you kernel files,
or kernel blobs, I guess. BOB NYSTROM: You don't
necessarily put them on disk. KEVIN MOORE: And then
the VM runs that. So the purpose of
the VM is to go as fast as possible from
source files, so uncompiled raw source files, to something
running as fast as possible. And so that's what
the runtime does. We have just-in-time
compiler, so we can get it running really fast. And then if you're
running for a while, we can optimize and generate
machine code as we're going. And then we have
some really powerful debug services that I'll
to talk about in a second. So we're going to start
filling out a table here. And right now, this is
kind of like the box thing, one column, one row. It's not exciting,
but we'll build more. So when you think
of development, native development in Dart,
that's the JIT and the VM. So if you're doing
Flutter development, that's what you're using,
not only on your test device, but the analyzer and
the footer command line tool, and the formatter,
and the doc generator. And that's all
running the DART VM. BOB NYSTROM: All of our tools
are written in Dart as well, so. KEVIN MOORE: So, what does
that give us in terms of speed? So, fast-- first, the VM
itself is really fast. We can get your code
running really quickly. But that's not good enough. Anyone who's done
rebuilds on native devices and waited to get the
screen loaded again, it's a really painful thing. It's really slow. It was painful for me
trying native development after doing a bunch of web stuff
where the web is just so quick. So we have two cool features. The first is hot reload. And again, for those
that aren't familiar, those that know Flutter
know this really well. You'll see I have an app
running on my little Android emulator on the right. I'm changing the plus buttons. You see the number increases. And then I'm changing the
color and source code. And I just hit Save. The color changes, but my count
is preserved until my animation loops back to zero. So this is amazing. I can change state in
my app, change something as fundamental as color, which
is actually propagated down to a bunch of different widgets,
and my state is preserved. What's really exciting
is, even things like if I'm down
15 levels in my app and I've gone through
15 dialog boxes-- I'm somewhere deep-- I can still do this trick. And I don't have to relaunch
the whole app and re-navigate to where I was to
see how it worked. So how do we do this? BOB NYSTROM: How do we do it? KEVIN MOORE: I'll tell you. So you had your IDE running,
coding along, you hit Save, and the IDE sends a hot reload
event to the Flutter command line, kind of the
Flutter engine running. That's talking to the front
end server, a Dart front end server. Now already, you're seeing
this interesting thing where, again, because we
maintain the whole stack, we can split these things apart. So we have the front end
running on your dev machine. And it takes that event
and it figures out, what are the set of deltas that
are affected by that change? And I'll only
recompile the Dart code in the kernel files
that map to that change. And then I'll only send
that delta to the device. So I'm not sending
a whole big app. I'm just sending the delta. And then when the emulator
running on your phone-- actually could be your
emulator or a hardware device-- gets that diff, there's
actually coordination with the framework,
and it figures out, is this the type of change I
can do safely with a hot reload? So obviously if you're adding
and removing classes, changing methods, removing methods,
you can't do that safely. But things like variables and
colors, you can do safely. And we can get that
really fast hot reload. So that's super exciting
and already saves people an amazing amount time. People love hot
reload in Flutter. But that's not all. We also have deep
introspection services. So again, you see emulator here. And on the left,
we have a web UI, that's actually also written
in Dart, that lets you inspect the running application. So you can click on
widgets on the right, and have it show up on the
left in terms of your UI, and see what you're looking at. You can click around
the UI on the left. It highlights it on the right. You can show things like
your layout boundaries. And this is enabled by these
debug services I talked about. So not only does Dart have
debugging services built in so you can get memory
allocation, object allocation, hot paths, code
coverage, all the things you want, it's also extensible. So Flutter was able to
build on top of those things and use data in something
like the kernel file to map back from the running
code, back to the source file, and give you this
kind of rich introspection. So that's the lightning
bolt. We build on top of an already
fast VM for dev cycle. And then we add
really powerful tools to make your dev experience
that much more productive and that much faster. But that's just half the story. BOB NYSTROM: Am I next? So if all that works
great, then you have this wonderful application
that you've enjoyed developing, and you've had a
good experience. But all of that is
sort of all for naught if when you run it on
end user's device, which may not be top of the
line, it's slow and janky. So, end user performance
is also critical. It's easy to get into this
mental trap of thinking about performance as just
how fast does my stuff go. But we think about it in a
sort of more multifaceted way. So part of the
performance story is how big is the generated code. The smaller your code is, the
shorter your download time is, which matters
especially in places where you don't
have great internet. It affects startup time. Startup time, in general,
is an important piece of the performance story. How much initialization,
code, other stuff has to run before
you can start getting to the interactive part
of your application and users can start doing
stuff they care about? And then actually,
what you normally think about with performance
is, how much code can you execute per unit of time? How fast can you make stuff go? And that matters,
because that's really the upper limit on how rich
of an interactive experience you can give people. But it's not enough to have
a good peak performance some of the time. You need to be sure that your
performance is consistently solid. Especially for interactive
apps on client devices, they want it to
be buttery smooth. It's not acceptable for
the garbage collector to wander off and lock
everything for two seconds while he's sweeping, right. So to have-- from a
user's perspective, to have good performance,
you need to do all four of these, which is difficult
for a high level language. So if you look at
what a JIT does, a JIT's job is to take a bit
of text that you just wrote and get it to
machine code that's running as quickly as possible. So it doesn't have a lot of
time to parse it, analyze it, optimize it. It just doesn't get to do a
lot of the classic textbook compiler optimizations. And that's the
right trade-off when you're in your developer
loop because you just want to see some results. But that doesn't benefit users. So in addition to
the JIT, we have AOT. We have an
Ahead-of-Time compiler. So what this does is,
when you're ready to ship your application, takes
all of your Dart code, including all the
transitive dependencies, all the libraries you use,
compiles the whole thing down to machine code ahead of time
exactly like you would do C or C++. The end result is you get
a native executable that contains your application
and the Dart runtimes, so the garbage collector or
runtime representation. And you get the
performance experience that you expect from an actual
natively compiled application. It starts up fast, runs
fast, runs consistently, there's no JIT warm-up,
that kind of stuff. KEVIN MOORE: So
that's the data side. Clear, so far? Good. BOB NYSTROM: So we've
already talked about Android. We've talked about x86 and ARM. KEVIN MOORE: Right. That's it right? BOB NYSTROM: What other
platforms are there? KEVIN MOORE: Funny
you should ask. Who is a fan of the web? I love the internet. BOB NYSTROM: It's all right. KEVIN MOORE: Actually, one of
my favorite things about Google, before I even joined
thinking about it, was it brought experiences
that usually you thought of, you had to buy and
install a big application, and made it available
on the web-- Sheets, Google Maps. The first time I saw Google
Earth on the browser, I was just blown away. The web is super powerful. There's no app store. App stores are nice. I don't, you know--
they have a place, but URLs are just
so easy, right? And so an important
thing to keep in mind, especially if your only
knowledge of Dart is Flutter, is that we've been
doing web a long time. Dart has been in web before
there was ever a Flutter. In fact, one of
our internal apps, Google Ads-- you might be aware
that Google does a little bit of ads business, right? The thing we use to let
people buy and sell ads on Google Search-- and as you can imagine,
that's not a small business-- that's all written in Dart and
has been for a couple years. This is millions
of lines of code, and it drives one of our
most important businesses. So Google has been betting
on Dart compiling and running on the web in
JavaScript for years. So we have a story here, and
the matrix continues to expand. We have a dev experience
with JavaScript and Dart that's great. We do analogous things
to what we do on native. In this case, what we do is we
take your individual libraries or modules. We compile those individually. Again, we can do
that really quickly. We compile them into JavaScript
that is meant to be looked at and read, generally. And source maps work well,
too, if you're on the web, for debugging. And we have some tools
that build on top of this. The idea is, again, if
you make a small change, we can be smart, understand
the impact of that change, only recompile a JavaScript
that was affected, and push only those
deltas to the browser. And we have some clever
hooks to the browser so that we can reload the app. We're not quite at the
hot reload stage yet. You do lose state. But actually we're
working, and we have a plan for how we can
implement that as well. So you actually get
the stateful hot reload where your counter,
your dialogue, is where you left it off. So that's the dev side. So that's the
lightning bolt, sorry. Now you can have it. BOB NYSTROM: So, you think of
DDC as a separate compiler. It compiles each Dart module
to a separate JavaScript file. That's great for
incremental compilation, only rebuilding the pieces of
your application that change. The downside of that is, when
it's recompiling a module, it has no way of knowing
which functions in there are used by other
modules, right. So it gives you everything. So the end result of this is,
it compiles your code quickly, but you get a large
amount of JavaScript. KEVIN MOORE: In fact, people on
the internet have been asking. It's like, the code is huge. No that's the dev compiler, yes. BOB NYSTROM: So if you've
done web development, you understand that
code size is king. So when you're ready to
ship your web application, we have a separate
compiler called Dart to JS. So this is-- I'll fill in the
other box there. So this is a whole program
optimizing compiler. So it takes-- again, just
like the OT compiler, it takes all of your Dart
code, all of your libraries, runs a bunch of whole
program optimizations on it, including a bunch of pretty
advanced dead code elimination. So it figures out which pieces
of libraries you're using you don't actually use. Discards all of that. Does a bunch of other even
performance optimizations. And then it gives you this
one monolithic ball of-- small ball, as much
as possible, of not very easy to read JavaScript
but very, very highly minified. What's interesting
is, the Dart language itself was designed for
this because we've always compiled to JavaScript. So because execution starts with
main, the top level of a file is not imperative code. Our static fields are
lazy initializers. All these sort of
language features that seem somewhat
arbitrary, and many of those were chosen in service
of being able to generate smaller JavaScript for
deployed applications. KEVIN MOORE: And they help
our AOT story as well, right? BOB NYSTROM: Mm-hmm. So if you look at this from a
project management perspective, having a language with
four independent back ends, this is a lot of
work to maintain. And especially when we want
to move the language forward, we don't want to have
to implement everything four times. What's cool about this
is that all four of these are built on now, in terms of
the same front end technology. So for example, the UIS code
features that we just shipped, those are mostly syntax features
that we can kind of compile down to the existing
kernel representation, which means in a perfect world--
it doesn't always work out this well-- we can advertise that
work across the four implementations, and then not
have to do too much back end work for these changes. KEVIN MOORE: So that's great. So we talked about the
native story and kind of in the context of Flutter. We talked about web. Some here at I/O
might have heard we're announcing the preview
of the Flutter for web work. So we're super
excited about this. It combines the best
of both stories. So how did we pull it off? So remember we had a
stack of Dart code, you have your app code in Dart,
you have the framework in Dart, and you had this blue box. How do you implement
it for the web? It was that easy. Just like that. That was it. No, it took some time. Although, you'd be
by be surprised, relatively speaking,
how little time. Because basically what
we did was-- again, if you know Flutter, there's
this kind of Dart UI library that is the bridge between the
Dart bits and the native bits. And effectively, we replaced
that and instead of mapping to native C++ bits, we mapped to
browser APIs, Canvas, and DOM. And so then we take that
library, that Dart UI library, all that Flutter framework,
and then all your app on top. And we send it through our
production amazing JavaScript compilers. And we give your JavaScript
that runs on the web. And so you end up with
a scenario like this. We have, actually, folks
from Reflectly here today, and they jumped on
this really quickly. The quiz. Which one of these is web and
which one of these is native? I'll give you a hint. BOB NYSTROM: I know. I know the answer. KEVIN MOORE: You've seen
this talk a few times. You see the mouse maybe
moving on the right one. That's the web. So I asked our friends, I was
like, how long did it take? And I didn't specify units. I probably should have. And they give me units of beers. It was four beers to
migrate from native to web. And he said he actually hadn't
finished the fourth beer yet. So somewhere south
of four beers. BOB NYSTROM: We don't know
the size of the beers though, so it's hard to tell
exactly how much. KEVIN MOORE: They're
Australian, so we don't. They were big. So check out Reflectly,
they're a great user of Dart and Flutter. So this is available now. We want you to take
a look and try it. Again, this is a preview,
a technical preview. There are a few caveats. Read those. But we'd love you to take
a look and try it out. We're super excited about it. [APPLAUSE] Thank you. It is cool stuff. And in other iterations
of this talk, I had all these other things,
because we run on Chrome OS. Now there's discussion
about running on Home Hub, Raspberry Pi,
obviously command line apps. They write a bunch
of those in Dart. We run on the cloud, Cloud Run. Our package sites
all run in Dart. People have compiled
Dart using Node, and they run it for
Cloud Functions. The SAS package that's
on NPM right now is actually sourced in Dart,
and then compiled to JavaScript, and published on NPM. BOB NYSTROM: You can't
talk about all the things. KEVIN MOORE: We run on all the-- I'll stop. But we run in a lot of places. And we try to do all that
following these three check boxes. So, we want you to pick three. And we're not so arrogant
as to say we've nailed this. It's always-- it's
aspirational for us. Let me know, I'm going
to stand back here. It's aspirational for us
and for the Flutter team. But we think we have
a really good story now around productivity, fast
experience as a developer, and at runtime,
and multi-platform. And we aspire to get better. And actually you have some
thoughts on that, right? BOB NYSTROM: I do
have some thoughts. So I think what we've shown you
is part of the answer for why Flutter chose Dart. They looked at the
design of the language and the implementation, the
maturity of the tools we had. But also I think
they were looking at where Dart is going
because this is a long term commitment for them. So I thought would be cool
to talk about some language features that we're
working on now that will be the sort of
next stuff that we ship. The first feature, this
is one that I have wanted for a incredibly long time. This is very close to my heart. The team right now is working
on adding non-nullable types to Dart. [APPLAUSE] The guy who's designing
it is a genius. Well, I guess the guy-- I guess Leaf and Lasse
are both working on it. They're geniuses. They're a joy to work with. So if you're not familiar
with this concept, I'll walk you through
it really quickly. So Dart has this core
library method tryParse. You give it a string, it tries
to parse it to an integer. If the string is
not a valid integer, it's defined a return null. The string not
int is not an int, so that's going to return null. And then if you try to
call .isEven on null, you're going to get
a runtime error. That's going to crash
your application. If it's in a shift
application, you're going to have a sad user, and
you will transitively feel sad. So non-nullable types, the
idea is finding these errors at compile time-- so being able
to discover them in your IDE before you run your code. The way it works is the type
system treats variables that can contain null as having a
different type from variables that cannot. So this would be an error
because tryParse returns a nullable int, so we can't
assign it to int because int doesn't contain nulls. You have to change it
to int question, which is how you say nullable int. And the other half of this
is the type system says, you're not allowed to
call methods on anything that has a nullable type. So then this becomes a compile
error that you need to fix. KEVIN MOORE: The compiler
will scream at you if you try to compile, and the
analyzer will red squiggles. BOB NYSTROM: It will
kindly tell you. KEVIN MOORE: Kindly, yes. No screaming. In red. BOB NYSTROM: So
this is part of it. But it's not enough to just
jam some stuff into the type system, because null is still
a useful value in your code. So you also need a set
of usability features to let you get in and out of the
nullable world so one of them, for example, is-- so in this case, you can see
that I've dynamically checked that number is not null. So we're not going to get into
the body here if it is null. So that type system is
smart enough to know that, OK, in the context
of that if statement, now we will treat that as having
a non-nullable integer type. And then it will allow
me to call methods on it, and that's fine. There's a bunch of other
usability language features we're working on for this. So we'll be doing something
kind of the union of lateinit in Kotlin and lazy in Swift. It will kind of cover
both of those cases. Doing definite
assignment analysis for an initialized
local variables. That's a sentence that gets
a lot of people excited at parties, let me tell you. KEVIN MOORE: It
is cool, trust me. BOB NYSTROM: Anyway,
the goal of this, if you kind of look at it. So this will be
correct code in Dart. KEVIN MOORE: And
really quick, too. And you don't have
to type whatever question mark all over. I could just put var there,
and all the stuff still works. BOB NYSTROM: Inference. It'll flow through inference. So the goal here is
that we're trying to give you the safety
of non-nullable types, but let you write code and
more or less the style you do today without worrying
about it too much. So that's great. The hard part is we don't
have non-nullable types today. So how do we get there? So there's a couple
of pieces to this. So first of all, the
system is designed to allow an
incremental migration. So you will be able to
take your Dart program, and in any order you want,
pick and choose different files and migrate them. You can migrate your application
before the libraries you use have migrated. Or those libraries
can go before you. The system can handle that. Even so, it can
still be a chore. So we are planning to ship
tooling that will automate most of this migration for you. So because we have
this open source front end that's written in Dart
that does static analysis, we can extend that to
do refactoring tools. So for the most of
the grunge work, it will try to do this
for you automatically. You do have to do
some of it yourself, because a big part
of this feature is you being thoughtful
about where you want to allow null to flow through your API. So that's a thing where you're
adding value to your code by writing that down. But for the stuff
that's not adding value, you shouldn't have to do it. The cool thing about
this is the system is designed such that
once your program and all of the libraries you
use have been migrated, it is fully sound. You will get zero null
reference errors at runtime. KEVIN MOORE: Provably. BOB NYSTROM: Provably. There's like, math. There's a meta-theory theorem. I'm not exactly
sure how it works. KEVIN MOORE: There's a
lambda calculus or something. BOB NYSTROM: Something. So let's say, imagine you
decide to make a new language, and you want your new
language to be successful. This is a thing that
sometimes people do. The easiest path
to success is you take an existing
language in an ecosystem, and you build on top of that. So you make a language
that runs on top of the JVM or on top of the JavaScript
ecosystem, and that's great. You get to leverage all of
that by having really seamless inter-op, right? KEVIN MOORE: And all the code
that's there just comes along. That's great. BOB NYSTROM: Right. The downside about that
is that means values are flowing into your language
from other languages whose type system you don't control. So in most other languages that
have added non-nullable types, they've done it in unsound
ways because of inter-op. So Dart, for better or worse,
has its own separate ecosystem. So this lets us design a
system that is fully sound. And what's really
cool about that is it means once we've finished
fully implementing this, we can actually take
advantage of this for optimization purposes. So when we're compiling
the native code, we don't need to
generate machine code for doing null checks. We can compile the
smaller JavaScript code because we know certain things
aren't going to have null. We can do unboxed
representations. So I'm super excited
about all of this stuff. It's not the only
thing we're doing. We've got some other
things in the pipeline. We're working on extension
methods at the same time. [APPLAUSE] It's so fun to have fun
features to talk about. KEVIN MOORE: I'm excited, yes. BOB NYSTROM: The
plan for this is, we're going to do basically
extension members. So anything you can
define inside a class, you can define as an extension. So we'll do methods,
getters, setters, operators. If you want to do operator
overloading extension methods, go to town. Actually, that is useful. Then you can do symmetric
vector operations. Great. KEVIN MOORE: Yes. BOB NYSTROM: We
are investigating some new concurrency primitives. I don't know a lot of details,
so I can't give them to you. But I'm sure they
are interesting. We're working on a new
foreign function interface. This should help you reuse
existing C and C++ code, which is important for
some critical stuff. And just generally,
other things. What I'm particularly
excited about-- this is one of the reasons
I'm on the Dart team is that we are a fully
open source language, and we do this in the open. So we have a separate
repository, the language repo, where all of the design work
for this stuff is happening. And I would love to
have you show up, participate, help
us do the design, help us make Dart
into the language that you all want it to be. KEVIN MOORE: And that's Dart. So we have a new
website, dart.dev. [? We want ?] you
want to check it out-- we just launched
this today as well-- to learn more
about the language, do some code exercises,
learn, dig in the community, ask us questions,
create packages. We're excited for you to
join us on this adventure and this ecosystem
we built together. Thank you. BOB NYSTROM: Thank you. [APPLAUSE] [MUSIC PLAYING]
I downloaded the Flutter Gallery again to see if it is actually fast yet, and I think they can say that now.
However users won't think it is fast until they fix the touch slop issue - when you start a drag it always "jumps" a bit at the start. It isn't technically a performance bug but it feels like one. In a way it is worse because it always happens.
This was a really interesting presentation and I am looking forward to some of the up-coming language features.