what's new in kotlin · 2019-08-25 · kotlin developers 0 750 1500 2250 3000 2016 2017 2018...

66
Tokyo Svetlana Isakova @sveta_isakova What’s new in Kotlin?

Upload: others

Post on 10-Aug-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Tokyo

Svetlana Isakova @sveta_isakova

What’s new in Kotlin?

Page 2: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Kotlin developers

0

750

1500

2250

3000

2016 2017 2018

156K

700K

2.2M

Page 3: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Timeline

… …

2017 Official on Android

2010 Project started

2016 Kotlin 1.0

2018 Kotlin 1.3

Page 4: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Kotlin evolution

Kotlin 1.2

Kotlin 1.0

Kotlin 1.1

Kotlin 1.3

Coroutines (experimental)

Coroutines get stable! Multi-platform projects can target Kotlin/Native (experimental)

Multi-platform projects (experimental) Kotlin/Native (experimental)

Kotlin gets stable!

Page 5: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Agenda

• Kotlin evolution • “Experimental” features

Page 6: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Agenda: experimental features

• Inline Classes • Contracts • Immutable Collections • Flows • Multiplatform Projects

Page 7: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Principles of Pragmatic Evolution

Language design is cast in stone, but this stone is reasonably soft, and with some effort we can reshape it later. Kotlin Design Team

* The real sculpture made by José Manuel Castro López

Page 8: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Principles of Pragmatic Evolution

• keeping the language modern

• comfortable updates

• feedback loop

Page 9: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

KEEPing the language modern

https://github.com/Kotlin/KEEP

KEEP = Kotlin Evolution and Enhancement Process

contains language proposals and the corresponding discussions

Page 10: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Comfortable updates

• Deprecation warnings in advance

• Automatic migration

Page 11: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Feedback loop with the community

• Kotlin the community

• Kotlin team listens to the community

• The community members influence the Kotlin evolution

Page 12: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Contributors from all over the world

Page 13: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Experimental features

Page 14: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Experimental features

The goal: to let new features be tried by early adopters as soon as possible

Page 15: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Experimental Language Features

• you need to explicitly opt in at the call site to use experimental features

compileTestKotlin { kotlinOptions { freeCompilerArgs += "-Xinline-classes" }}

Page 16: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Experimental API for Libraries

• can be publicly released as a part of the library

• may break at any moment

Page 17: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

@ShinyNewAPI class Foo { ... }

Experimental API

@Experimental annotation class ShinyNewAPI

You can mark your new class or function as experimental

Page 18: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Using experimental API

@UseExperimental(ShinyNewAPI::class) fun doSomethingImportant() { val foo = Foo() ... }

Page 19: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

• feedback loop for new features and API

Experimental: Summary

Page 20: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Inline classes

Page 21: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Inline classes

• can wrap values without additional overhead

• currently an experimental feature

Page 22: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Duration API

• KEEP: Duration and Time Measurement API

• status: experimental in Kotlin 1.3.50

• uses inline classes

Page 23: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Refining API: trying primitive args

fun greetAfterTimeout(millis: Long)

greetAfterTimeout(2) // meaning 2 seconds?

Too easy to make a mistake

Page 24: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Refining API: trying overloads

fun greetAfterTimeoutMillis(millis: Long)

fun greetAfterTimeoutSeconds(seconds: Long)

greetAfterTimeoutSeconds(2)

Too verbose

Page 25: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Refining API: trying class

fun greetAfterTimeout(duration: Duration)

greetAfterTimeout(Duration(2))

Extra object is allocated

class Duration(val value: Long)

Page 26: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Inline classes to the rescue

inline class Duration(val value: Double)

fun greetAfterTimeout(duration: Duration)

fun greetAfterTimeout_(duration: Double)Under the hood:

No extra object is allocated! ✓

Page 27: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Inline classes constraints

inline class Duration(val value: Double)

fun greetAfterTimeout(duration: Duration)

inline class can define only one val property

Page 28: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Creating Duration

fun greetAfterTimeout(duration: Duration)

greetAfterTimeout(2.seconds)

✓Explicit units in the code

val Int.seconds get() = toDuration(DurationUnit.SECONDS)

Page 29: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Inline classes: summary

• KEEP: inline classes

• help to improve API and avoid extra allocations

• you can go and try it out

Page 30: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Contracts

Page 31: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

inline fun <R> run(block: () -> R): R = block()

inline fun <R> run(block: () -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }

Changes in standard library

Page 32: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Changes in standard library

inline fun <R> run(block: () -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }

inline fun <R> run(block: () -> R): R = block()

Page 33: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

We know something about run, that the compiler doesn’t

val answer: Int run { answer = 42 }

println(answer)

Compiler error: Captured values initialization is forbidden due to possible reassignment

Page 34: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

val s: String? = "" if (!s.isNullOrEmpty()) { s.first() } Compiler error:

Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?

We know something about isNullOrEmpty, which the compiler doesn’t

if (s != null && s.isNotEmpty()) { s.first() }

Page 35: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Kotlin Contracts

…allow to share extra information about code semantics with the compiler

Page 36: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

inline fun <R> run(block: () -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }

Contract: block lambda will be always called once

val answer: Int run { answer = 42 }

Page 37: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

fun String?.isNullOrEmpty(): Boolean { contract { returns(false) implies (this@isNullOrEmpty != null) }

return this == null || this.length == 0 }

Contract: if the function returns false, the receiver is not-null

val s: String? = "" if (!s.isNullOrEmpty()) { s.first() }

Page 38: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Contract = explicit statement about function behaviour

Why can’t compiler just implicitly infer such information?

Because then such implicitly inferred information: - can be implicitly changed - can accidentally break code depending on it

Page 39: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

• handy functions (run, isEmptyOrNull) are even more useful

• contract DSL will change

• more use-cases in the future

• you can define contracts for your own functions

Contracts: Summary

Page 40: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Immutable Collections

Page 41: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Standard library: Collections

MutableList

List

read-only

Page 42: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Immutable collections

MutableList

List

ImmutableList

PersistentList

trulyimmutable

supportsmodification

read-only

Page 43: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Persistent collection modifications

val list = persistentListOf(1, 2, 3)

val newList = list.add(4)

println(newList) // [1, 2, 3, 4]

Modification operation returns new collection:

Under the hood, newList shares parts of data structure with the original list

Page 44: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Persistent collection modifications

val list = persistentListOf(1, 2, 3)val newList = list.builder().apply { add(4) add(5)}.build()println(newList) // [1, 2, 3, 4, 5]

Applying several operations:

Page 45: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

• KEEP: Immutable Collections

• Will be part of the standard library in the future (no promised date)

• You can go and try it out

Immutable Collections: summary

Page 46: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Flows

Page 47: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Flow

• suspend-based reactive stream

flow { emit(value) } .map { transform(it) } .filter { condition(it) } .catch { exception -> log(exception) } .collect { process(it) }

Page 48: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Integration with RxJava

Use extension functions:

• flow.asPublisher()

• publisher.asFlow()

Page 49: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Backpressure

• Backpressure happens automatically thanks to suspension mechanism

Page 50: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Flows: summary

• bring reactive streams to coroutines library

• currently in an experimental state

• will get stable soon

Page 51: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Multi-platform Projects

Page 52: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

expect fun Char.isUpperCase(): Boolean

public actual fun Char.isUpperCase(): Boolean = java.lang.Character.isUpperCase(this)

Now:

fun Char.isUpperCase(): Boolean = java.lang.Character.isUpperCase(this)

Before:

expect / actual in standard library

Page 53: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Multi-platform projects

BrowserKotlin/JS

AndroidKotlin/JVM

iOSKotlin/Native

ServerKotlin/JVM

commoncode

Page 54: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Sharing common code

• Sharing business logic

• Keeping UI platform-dependent

• The shared part might vary

Page 55: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Common code

• you define expect declarations in the common code and use them

• you provide different actual implementations for different platforms

Page 56: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Time measurement example

expect fun measureTime(action: () -> Unit): Duration

Expected platform-specific API:

Expected API can be used in the common code:

measureTime { // operation}

Page 57: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Platform-specific Implementationsexpect fun measureTime(action: () -> Unit): Duration

actual fun measureTime(action: () -> Unit): Duration { // implementation using System.nanoTime()}

actual fun measureTime(action: () -> Unit): Duration { // implementation using window.performance.now()}

actual fun measureTime(action: () -> Unit): Duration { // implementation using std::chrono::high_resolution_clock}

Kotlin/JVM

Kotlin/JS

Kotlin/Native

Page 58: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Common code

• can use the standard library

• can define expect declarations and use them

• can use other multi-platform libraries

Page 59: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Multi-platform libraries

• Standard library

• Ktor HTTP client

• kotlinx.serialization

• kotlinx.coroutines

• … and more

Page 60: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Many apps already in production

Going Native: How I used Kotlin Native to Port 6 years of Android Game Code to iOS in 6 months

Shipping a Mobile Multiplatform Project on iOS & Android

Your Multiplatform Kaptain has Arrived:  iOS release is powered by Kotlin Multiplatform

Page 61: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Multi-platform projects: summary

• a modern approach to multi-platform development

• you can easily tune what parts you want to be shared

• you can go and try it out

Page 62: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

More about Kotlin

Page 63: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because
Page 64: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Kotlin course at Coursera

Page 65: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Hands-on lab “Intro to coroutines & channels”

http://kotl.in/hands-on

Page 66: what's new in Kotlin · 2019-08-25 · Kotlin developers 0 750 1500 2250 3000 2016 2017 2018 156K 700K 2.2M. ... Why can’t compiler just implicitly infer such information? Because

Have a nice Kotlin!