ROMAIN GUY: Good
morning, everyone. [APPLAUSE] Wait, don't cheer us. Cheer the next speakers. So I'm Romain Guy, representing
the Platform team on Android, and this is Tor Norbye
representing the Tools team. But you're not here for us. You are here for very
special speakers. TOR NORBYE: Yeah,
so Romain and I have been incredibly
excited about this official announcement of Kotlin. We both love Kotlin, in case
you hadn't noticed already. And we don't take any more time
from the speakers of honor. So without further
ado, here they are. [APPLAUSE] HADI HARIRI: Hello, everyone. Aw, that's nice. So I was thinking the other
day, the first time that I ever did a talk on Kotlin, it was
like 4 and 1/2 years ago. And they gave me a room for 900
people and 7 people showed up. So it's kind of nice to see
more of you show up today. Thank you. [APPLAUSE] Anyway I've got roughly
around 30 minutes. Actually, a little bit less. 28 minutes to give you a
whirlwind tour of Kotlin, so I'm not going to cover
the entire language. I'm going to try show you
as much as I possibly can and how you can use it
and where it provides you with some benefits, OK? So I'm going to try and do
it all with live coding, so if it all goes terribly
wrong, there's a Google video-- I mean there's a YouTube video
of this somewhere as well. So you can watch that. OK, so we're going to start
with something very simple that you've already
seen, data class. And I'm in a file called main. So data class, I'm going to
create a new type called money, and it's going to happen
amounts which is of type Int. I know, don't say
anything for now. And it's going to have a
currency of type string. OK? And this is both
properties, and they're going to be read
only properties. So this is something that
you're already familiar with. It's essentially a data class. Let's go ahead and
compare that to a Java one that I have done earlier. So split vertically. And let's get the Java
money up-- actually, let's go down this side. Java money-- so there you go. That's kind of the equivalent of
what I've just written, right. A JavaBean essentially,
a data class that provides two getters. They're immutable,
so they're read only. And this data modifier over
here, what that's doing is essentially giving me
a whole bunch of things, like the to string, it's
giving me the clone, which in Kotlin it's called
copy, it's doing the equals, it's doing the hashCode. Now you say, OK,
well that's great. Brilliant, but why
do I need that? Because any good IDE is going
to generate that for me. It is true, it does. But the problem is
that that's code you're going to have to maintain. And every time you
add a new property, you're going to have to go
back and change that code. And the other issue that
you're going to have is you don't know, in fact,
if that code is the standard stuff that Kotl-- that IDE has generated
for you, or you've tweaked it a little bit. OK? So it's not just about saving
on typing on the first line. Right. Now what I'm going
to do is go ahead and create a function main. Let's close this guy over here. And this is the top
entry point of Kotlin, so you have a public static
void main in a class. You don't need that in Kotlin. So in Kotlin, you can put
everything in the top level. It's kind of like
JavaScript in a good way. And so you don't have to-- and I want to reiterate,
every function and everything that I'll show you today,
I'm going to just add it in the file as a
top level thing, but that doesn't mean that
you don't have any more member functions. Anything, any class,
even a data class can have member functions. But for brevity
and for the purpose of what I'm showing
you, I'm just going to put it
as top level, OK? So I'm going to create
a new instance of money. We're going to call it,
for example, tickets. And I'll say Money 100, and
it's going to be dollars, right? And I'll get into the
explicit type here, but essentially here what
I'm doing is type inference. So Kotlin is very strong
in type inference, and as much as it can
infer, it will for you. So you don't have to
explicitly tell the type. And then I'll say,
for example, popcorn. Let's say tickets, copy, right? So what that's going
to do is basically copy the previous one for me,
and all of the properties. So if I don't pass
any parameters in, it's going to just take the same
values as it has before, OK. So I can pass in a
new parameter and say, you know, in Spain,
for example, popcorn is seven times the price
of the entry of the cinema, so that's going to
be like 500 euros. Right? And now I can do things
like, for instance, if tickets is not
equal to popcorn, then println "they
are different!" So what this is doing is a
property comparison one by one. It is not doing a
point of comparison. For point of comparisons, we
have the triple equal, right? Different to
JavaScript, there isn't a chart of 600 different
positions you have to remember. And this, by the way,
is font ligature, so don't get confused
with that, we didn't introduce a new symbol. OK. So I can go ahead
and just run this, and I get they are different. And if I change this to 100
and I put this as dollars and I run this, it's going
to say to you that nothing, because they are the same. OK? Now one of the features
we keep boosting about is the interop between
Java and Kotlin. So we have this Java
money one over here, so I'm going to go ahead and
create an instance of it. I'll say javaMoney equals
javaMoney, and it will be 100 and it'll be dollars. And then if I do
javaMoney, you can see that I don't have any getters. Well, I do have, actually, a
getter, so I can do get amount, but if I write
getAmount, complete it, the IDE's already going to
replace that for property, because we don't have really
like getters and setters, we just have properties. So that's consuming
Java from Kotlin. And if I go over to the
Java over here, and let's go ahead and create a
public statics void main, and I'll do-- so let's see, I've got
to declare the type. Money equals new money,
100, and dollars, and-- OK. That's the other thing. Semicolons in
Kotlin are optional. And the reason
they're optional is so that you can have
endless arguments over whether you should
use them or not. We are trying to compete
with JavaScript there. OK, so money.getAmount. So now I'm using a Java type--
sorry, a Kotlin type from Java, so I'm getting the getters
and the setters, right? So idiomatic depending
on how you are using it. And that's just different Java
files, different Kotlin files in a single project, working
seamlessly without any issues. Right, so now let's go ahead
and create some functions. So I'm going to create a
function called sendPayment. That takes a money-- and Money-- and it's going
to println the money out. And of course we have
string interpolation, so I could say,
sending money.amount. And you don't have to put
these curly braces if it's just a single property that
you're passing in, as we'll just see in a moment. So now I can call this
and say, for example, sendPayment, tickets, right? Now Kotlin, we also have-- notice one thing here, I'm
not defining the return type. By default it's unit,
which is kind of like void, but it's not. It's actually a object which
is essentially a singleton, a single instance of an object. And if it is a unit, you don't
have to put it there, right? So I'm going to add
a new parameter here and I'm going to say, for
example, with message. And this is gone to
have string, and you can have default parameters. So here, notice that there's
no compilation error because I made a default parameter. This saves you a lot in
times of overloaded function, overloaded member
functions, right? I can just have
default parameters and then do what I want. And you can have multiple
default parameters. And since you can have
multiple default parameters and you can alternate which
one you want to pass in, you can also do
names parameters. So, in fact, I could say
message equals "Good luck!" and money equals tickets. And this is kind of useful
as well when you are using-- you're talking to legacy
code, for example, some function that you can't modify,
and it's got 600 parameters, and they're probably 500 of them
are true and false Booleans, it kind of gives you some
insight into what parameters I'm passing in in
every position. Oh yeah. I love it when people crap-- clap. [LAUGHTER] And I'm thinking to myself,
well this is going well. Anyway, right, let's go. Edit that out, like
adult supervision. Right. One other thing with
Kotlin is that when we have functions that
are really, really easy, like essentially
returning a single value, you can just do single
expression functions. So I omit the return
type explicitly, I omit the curly braces, and I
just return the actual function that I want to do. OK? So, in fact, the
concept of expression comes in many places in Kotlin. So for instance, let's
create another function that's called convert
ToDollars. convertToDollars, and this is going
to take a money. Money, and it's going
to return Money. And then what we're
going to do here is a when statement, so that's
essentially case, right. So when money_currency
is dollars, then we'll do return money
as is, right, because I don't need to do anything. And if it's EUR, then what
I'm going to do is return, we're going to do
money.amount times-- sorry, I've got to
create a new instance. Money, and then it's going to
be money.amount times BigDecimal 1.10, and then that's
going to be dollars. And else, throw
IllegalArgumentException, "not the currency
you're interested in!" So this you can actually
treat a when as an expression. So I can remove this return over
here, remove this return over here, put it just here,
and then this just makes the when always
return an expression. And in fact, you can even
remove the return here, remove the Money here,
and remove that there, and you get a single expression. OK? Single expression function. Now one thing that
you notice here that this is giving me an
error because this is-- I'm trying to operate a
BigDecimal with an int, so we're going to go
and refactor this, and we're going to
call it BigDecimal, OK. Now talking about
BigDecimal, oh, here we go. BigDecimal, BigDecimal
100 and BigDecimal-- I love typing BigDecimal. I love it. So we've got this over here. Now if you look at,
actually, BigDecimal-- so if I create a new
BigDecimal, we'll call it bd1 equals BigDecimal 100. You can see the bd1 gives me
a whole bunch of functions like divide, multiply,
all of these things. What if I wanted to do
something like a percent? I wanted a percentage
of BigDecimal. Now normally you
would, basically, inherit from that and then
create your own version and have all of these
things, but in Kotlin, one of the features
that we've added-- and if you're familiar with C#-- is called extension
functions, which essentially means that you can take any
class, any type, and extend it. So I can take a
function of BigDecimal, I put the name of the class
that I want to extend, and I say I want
to do a percent. And what is the
percentage that I want to do, for example, an
integer, and then it would be, let's see. So given that this is
an extension function, it's going to have an instance
of that class, of that object, right. So I can use that,
reference that with this. And I say this multiplied
by the percentage-- and then this has got to to
be wrapped in a big decimal again-- percentage. And then that divide-- and then another BigDecimal 100. And what's wrong with this,
that should be percentage. So percent-- age. OK, so now what happens is
that on bd1, I have percentage. OK. And I could do percent
7, and that would give me a certain percent. And that extension function
gets included anywhere where it is defined in the package. So here in this case, I
have it in com.jetbrains.gio and that will get
included there. So you can create
extension functions, and we'll see that the
standard library actually consists of a whole bunch
of extension functions. Now we'll take this
one step further, because I can actually
extend everything. So let's go ahead and
extend an integer. So I'll say fun Int. percentOf and here
will do the reverse. So I want like 10 percent
of something, right. So I'll say money, for instance,
I want 10 percent of money. And that's going to return the-- let's see, it's going
to return money. Then it will be amount.multiply
and then here it's going to reference the actual
instance, so it will be this-- and again, this has to
be wrapped in BigDecimal, and then divide by 100. OK. And I think I got that
in the right order. If the implementation is
wrong, doesn't matter. Who cares. Anyway, so now what I can
do is something like this. Seven percentOf BigDecimal 100. OK? Oh no, sorry. Money. So I can do Money--
no, don't clap yet. Money. Oh, let's just take
the money I have. 7.percentOf(popcorn). OK, nice? Let's do a little bit nicer. What I want to do is, in
fact, something like this. I want to do 7
percentOf popcorn. That would be nice. And you can actually do that. You see that little
wiggly there? Squiggly? Alt, Enter, add 'infix'. There you go. OK so any extension function
that has a single parameter can be called an infix notation. And what I've done
is essentially add the infix over there. And this is some
of the things that allow you know, with Kotlin,
to kind of create the whole DSL approach to things. Right. So one thing that I hated doing
here is all of this BigDecimal. That's a pain. And in Kotlin, when you want
to create a value of type long, you can say long 100L, and
that will be of type long. And it would be
awesome if I could do like, bd2 equals 100BD,
but you can't, and we don't have that built in. But what we do have in Kotlin
is called extension properties. So they're exactly like
extension functions, except they extend
with properties. So I could do something
like .bd, right? And now-- or let's, so now-- see, it even says, do you want
to create an extension property on type integer? Yes. So this is going to
return a BigDecimal. And then here, I'm going to do
return BigDecimal, and this, which is the instance. And I can, in fact, convert
this to an expression to make it easier. So there you go. Now I have 100.bd. So when I'm passing
that in, it looks much nicer than BigDecimal,
I could just do 100.bd. OK? And one other thing around
functions that you can do is, there are certain
operators that you can extend. So you can extend, for
example, the plus operator. And what I'm going to do is
I'm not going to type this out, I've just got a
nice little thing that has done that for me. See how fast I am at typing? So what I've essentially
done is now override the plus operator for money. So now I can say costs equals
tickets plus popcorn, right. And that allows me to
add to monetary amounts. OK, you could do that with
plus, minus, multiply. A bunch of built-in
conventions that you can follow for certain operators
that allow you to do that. OK. So we've been creating a
whole bunch of types here. And let me go ahead and delete
all the stuff so we can focus. We've been creating a
bunch of types here. Notice that in any of these
types that I've created, I've never actually specified
the type, and you can. So I can do, for
instance, val train costs, for example, train
is of type Money and then initialize it
to some new value, right. 100.bd, and then dollars. Now if I go ahead
and do train=null, it's going to give me an error. And it's going to give
me actually two errors. One of them is because
that's immutable variable. So I can fix that. I've now made this mutable. You see that the
IDE underlines it, so it wants to point it out
that this is really something you're going to shy away from. We don't enforce
immutability in Kotlin, but we kind of do recommend it. Like all of the lists
and all of these things are immutable by default. So I can't assign null
in Kotlin because Kotlin tries to get rid of the
null pointer exception by saying that types aren't
nullible by default, right. But there are
times when you want to have a type that is
nullable for whatever reason, you're bored. And you can add a question
mark, and then that will give you the ability
to assign null to that type. Now normally when you're
working with Kotlin, you probably don't
want to do this. You probably don't want
to have nullable types, but since we're interopping
with Java, Java can be null. So if I create a function
here that is, for instance, fun javaMoney, and that
takes money of type JavaMoney and does whatever with it. So let's say I do println
money.amount is valid. So this can be null. It could, if it's
called by an instance that a function that,
for example, is returning this type, it could be null. And you can indicate that
by adding the question mark. When you do that, you
can see that the IDE is going to give you error. It says only safe operators,
or the double exclamation mark are valid here, because
it's essentially saying you're going to run into
a null reference exception. So there's two ways
you can solve this. First of all, you can say,
for example, money, not null. And then do a if not null, then
go ahead and operate with it. Put this one upstairs in there. OK. That's one way. Or the shorter way is just to
use the safe operator or Elvis operator, which is over here. So now we just say if money is
not null, then do something. Now if you want to have
fun, you can also do that. And that says, I know
it's null, but I want to shoot myself in the foot. OK? And you've got to be
careful with that, because a lot of times when
people start with Kotlin, they get all of this little
squigglies over here, and they're like,
well I actually don't know if it's going
to be null because I really want it to not being null. So I'm not going to handle
the case where it's not null, so I'll just do that. And then they run the app and
they're like, wait a minute, you set Kotlin got rid of
null reference exceptions. Yes. OK. What else. Right. So let's switch to
some other stuff, like higher order functions. Now you're all familiar with
a high order function, which is basically a function
that takes a function or returns a function, and
we have those in Kotlin. So we can say findEmails
users List of User, and then I'll create a new
function, which is a predicate. So I'm passing in a
function here, right, a function that takes a
string and returns a Boolean. OK? And then this probably is going
to return a list of users. So essentially what
I'm doing is I'm filtering on a list of users. Right. So I'll do this later. To do later. OK. This to do, by the
way, is built in. You can use it instead of
not implemented exception-- non implemented error. And it does a additional
thing that we won't get into, but nothing is actually
very nice in Kotlin, but we won't cover that now. It's nothing to worry about. I just made that up. OK. OK, thank you. So now how do I use this? I can do findEmails,
right, and I'll say-- I actually have a user,
let's create some users here. So usersFromJSONFile. And I have some uses
over here, so users.json. So this is actually a
function that I have ready, which is basically using json
to read some users from a file. And this is a
typical data classs that you've already
seen, the only new thing here is that this also got
an enum class with a property Role. OK? So now I can do like
users, and then I'll pass in that function. Now I can pass in
the name function by using the column
column reference, or a can pass in a lambda. And in Kotlin, lambda
follows this syntax. You pass in the parameter name,
and then you say, for example, the parameter name
ends with right .com. So I'm getting a list of
users that end with .com. Now when you have a single
parameter in Kotlin, you can actually omit
having to explicitly mention it and replace it with it. So similar to Groovy,
you can just use it. The other thing that
you can doing in Kotlin is when the last parameter to
a function is another function, you can actually not
include it in the brackets. So it feels a little
bit like it's outside. And this is, again, one of
the characteristics that allow us to create nice
DSLs, and you can even do this like multi-line. So if you look at
findEmails now, in a sense it could actually feel like
it's part of the language, but it isn't, it's
actually a function. And when we implemented
aasynchronous programming with coroutines, we didn't
like-- you know, if you're familiar with C#,
C# does their sync or wait, there are keywords
in the language. In Kotlin, there
are not, they're essentially just functions. So that gives you
the flexibility of deciding how you want
to do different things. Now you don't have to
do all of these things, because all of these
things are built-in. So, for example, if
I say dotComUsers, I say users.filter, and you can
see that as I complete this, it actually opts for the
version of including out of the parameter. So I can say the
email.endsWith .com. And then I can go
and sort by it.id. And then let's go ahead
and do, for example, map that to a pair of
it.email and it.username. OK? So all of these
functions are actually built in in that
small standard library that ships, that you're not
going to problems on Android, it's very small. And they're all in,
essentially, extension functions on top of collections,
generic collections. So you have all of those
functional things that are very in fashion these days. And so this obviously
gives you a pair, and in fact, you can do
this even nicer, if instead of doing pair, it, to. So a map, email, to username. And guess what it is? It's just an infix function
that creates a pair. OK.? Now sometimes I don't go
through the whole map. I just want to, for example,
say get back a single element. And what you can also do
is destructure classes, data classes in Kotlin. So I could do something like
id, username, and email. OK and then I can
just use the ID. And this is great, but then
the IDE complains and says, well this variable
is never used. In that case, you
can actually replace that with an underscore. So there you go. And you can destructure
the values you want. Anything that you don't want to
use, replace with an underscore and you're good to go. Right. So what else can I show you? OK. So I've got some
other code here. If you're familiar with the
concept of algebraic data types, it's
essentially a type that can be of one type or another,
like for instance a Boolean. Now in Kotlin, the way that
we do that is with coclasses. But before I get
into that, let me go ahead and do an open here. Notice the first thing
here, that user result is giving me an error. Because by default in Kotlin,
you cannot inherit from classes. So all classes are
essentially final. If you want to
inherit from classes, you have to use the
open modifier, right? Now I've used the
sealed, and the sealed is essentially saying
that this is the hierarchy that user result has. Like, there's not going
to be any other class anywhere that is going to
inherit from user result. Everything that's going to
inherit from user result has to be in the same file, or
you can make these, of course, subclasses. So I could move this up there
and this would be a subclass, but then I would have to
prefix it with user result. OK. Now I've just created
it as a class outside, So why would I want to do this? Because it looks good. No. Well, this is actually
good because when you're doing some things, it's often
like your invoking a function and you're like, OK,
well if it's successful, I want it to return a value. If it's null, I'm going
to pass in a message. And then you get this type that
contains the values that you want to return when
it's successful, it contains the types that you
want to return when there's a message, and then
you've got to figure out the semantics of which
properties are applied to an error situation,
which properties are applied to non-error situation, or you
can just throw an exception. In this case, you can
use a function that basically returns two types. And then based on the
result, do different things. So here I say, for
instance, when-- let's create an instant val,
result equals userresult-- sorry, retrieveusers. So now I can do when
result is success, then we're going to do,
for instance, well we're going to get the
result, and then we're going to do users
forEach println the name. OK? username. And then we're going
to do a failure. Result println result.message. OK? So now based on
the result, based on the type that is returned to
me, I can do different things. I notice one thing over here,
that this has gone green. I don't know if you see
it on the big screen, but this has gone green. And this is a Smart cast. So that's another thing
that we have in Kotlin, and you saw that when I
was doing the null check, that is said this is not null,
because it is Smart casting. So you don't have to explicitly
come over here again and say, oh, I know that this is of
type success, let me go ahead and cast this to type success,
to then access the property. The compiler will do
that for you, that's what the smart casting is. Right. And last but not least,
before hand it off to Andrey quickly just mention, also,
that a lot of the things you've been seeing with the filter
map, all of those things, those are essentially
eager evaluation. But we also have the ability
to do lazy evaluation. So I can do val, for example,
sorry, generateSequence, and then have something,
for instance, 1. And then here, we'll do it times
10, and then we'll do values. Now I'll say values.take(10),
and then forEach println it. Now this is essentially
creating a sequence, a generator that is infinite. It's never going to stop. It's going to start at
one and multiply by 10. But what I'm saying here is that
I just want to take 10 elements and then print them out. And what it will do is basically
consume that until it hits 10. It prints out-- go away-- it prints out a
beautiful Christmas tree that's one-sided. OK, pyramid, whatever,
and stops there. And anything that you
have, like for example, the users that we had, users
from Jason, users.json, you can say asSequence and
convert it into lazy evaluation as well. OK? That's all we have the
time to show you today. Obviously, there's way
more to the language. Go online, learn
everything about it, and thank you very much. And I'll hand it off to Andrey. ANDRY BRESLAV: Thank you, Hadi. Hello, everybody. So as you've seen Kotlin already
has many things in store, but I am the nasty person who
adds new futures before you learn the existing ones. So I'll be tell you
stories now, but I'll need to find a clicker. Do I have a clicker? No, OK. OK, so I'll be telling
stories without a clicker. So my job here is to
tell you about what we're going to have in the
future versions of Kotlin-- oh, thank you very much. And the first big thing
we're working on now is platforms, supporting
different platforms. So historically, Kotlin
compiles to JVM bytecode, same as the Java
programming language. So we can run a
server on the desktop and of course on Android. And it's just the same
bytecode everywhere, this is why we can run
old versions of Android as well as new ones. But the story doesn't
end there, because we are adding new platforms. And recently, we've added-- but God doesn't like platforms-- recently we added
JavaScript, which means Kotlin can now compile
to JavaScript code and run in the browser or on node.js. So now we support three, major,
very popular virtual machines, JVM, Android Dalvik,
and JavaScript VMs. But there are many
US cases where a virtual machine is not
practical or is simply unavailable. For example, for
iOS, virtual machines are severely restricted. You can't do dynamic
code generation, or for a small embedded
system, a VM doesn't fit in. Or for, say, a Linux
command line tool, the VM will be a starting
tool for too long. So it's a no go
there, and that's why we're working on something
called Kotlin/Native, it's currently available
as a technology preview. And there, we basically use
LVM to compile Kotlin down to a native code, to
stand along binaries that can run on different platforms. Currently, we support
iOS, Linux, and Mac, and Windows is in the works. So this is taking us to
this vision with Kotlin, when it can run
inside every component of a modern application,
on any platform you like. So think full stack
web applications with the server and the
client both written in Kotlin, or think reuse code between
mobile platforms, Android and iOS for example. Or mix the two
previous use cases and get like a real
multiplatform scenario. So our vision for
Kotlin is having different models
in the same project compile to a
different platforms. And of course, you we want
to share code there, right? Because if you support
so many different things, you want to run the same
code in different places. And we're working on
making that possible. But there is a very
important thing, because previously,
many projects tried to unify platforms. And this often ends up
being like the least common denominator, when you
take only things that are available on all
platforms, you are basically stuck with a minimal
interface, and that's something we don't want to have there. So we want you to
be able to use all the platform-specific
fancy APIs like the newest version of Android or something
else as much as you like. And if you want to
share some code, only then you have to
resort to some common APIs. So the idea there is that you
have a common model with lots of business logic and stuff,
and it can work side by side with a platform specific
model written also in Kotlin, and those two can
talk to each other. So when you need, you
leverage the platform API, and when you need, you
use the Kotlin code. So take away here, our
future is multiplatform. Next-- oh. Next big thing is couroutines. So the rationale there is
pretty straightforward, everybody needs to write
asynchronous code, right? Because the world is too big
now for sequential execution. And it's our reality,
but it's hard, right? Who has written
asynchronous code? Quite so many hands. Those of you who don't actually
will be doing this very soon. And the problem is, it's
rather hard, actually, to write sequential code. Or it was hard before
languages learned to support you in doing that,
because a language can help you there a lot. So basically what we have
with coroutines in Kotlin, you're right asynchronous
code the same way you write synchronous code. So what do you use
in synchronous code? Loops, ifs, breaks
and continues, things like that, right? And it's the same things
you're using with coroutines for asynchronous code, so
that the language keeps track of everything and you don't have
to express an intricate control flow for a synchronous
computation in your code. No call backs, no fancy
functional structures, it's just plain old
sequential-looking code. And isn't it cool? Thank you. So the idea with coroutines
is that you basically have the same abstraction for
asynchronous and synchronous. And also, it's a nice
metaphor to think of them as almost free of threads. Like here is the only code
example I'm showing you. Basically, very many things
that are traditionally done with threads can
be done with coroutines, but coroutines are
extremely cheap. So here on the slide,
I have a code that creates 100,000 coroutines. Think about that. 100,000 coroutines existing in
parallel, and each one of them waits for one second
and returns one. So this program completes
in, completes in one second, almost one second,
because all the coroutines wait in parallel, of course. But if you tried to do this with
threads, it just doesn't work. 100,000 threads don't
fit into memory. That's it. So with coroutines, it's
a win-win situation. You get lots of performance,
so it's very efficient, and the code is simple. So take away here,
check out coroutines, because our future will likely
to even more asynchronous than our present. So I'm almost done,
and if you want to learn more about Kotlin,
check out our website. We have a section for Android. And also, we'll have a question
and answer session right after this talk, so come over
to the Developer sandbox, section C. Myself and Hadi will
be answering questions there. So thank you very much
for your attention.
Best blunder at I/O this year
super intimidating to me. didn't seem to "intro" ish for me. What are good resources for kotlin besides Koans?
Hadi is the man
Super cool talk
As an Android developer with C# background, I'm so happy to have Kotlin awesomeness at my disposal.
What is cool is you can write Java and AS will convert to Kotlin so helps in learning Kotlin.
Anybody happen to know what font this is? I'm not satisfied with my current ligatures from iosevka.
Might soon be possible to code in Kotlin, on android. https://github.com/termux/termux-packages/issues/1028
As in, compile on an Android device.