What's new in Kotlin?

What's new in Kotlin?

Presented at Kotlin Fest Tokyo 2019.

C6997ce411091d4a51ea3caa2109c0b0?s=128

Svetlana Isakova

August 24, 2019
Tweet

Transcript

  1. 4.

    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!
  2. 6.

    Agenda: experimental features • Inline Classes • Contracts • Immutable

    Collections • Flows • Multiplatform Projects
  3. 7.

    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
  4. 9.

    KEEPing the language modern https://github.com/Kotlin/KEEP KEEP = Kotlin Evolution and

    Enhancement Process contains language proposals and the corresponding discussions
  5. 11.

    Feedback loop with the community • Kotlin the community •

    Kotlin team listens to the community • The community members influence the Kotlin evolution
  6. 14.

    Experimental features The goal: to let new features be tried

    by early adopters as soon as possible
  7. 15.

    Experimental Language Features • you need to explicitly opt in

    at the call site to use experimental features compileTestKotlin { kotlinOptions { freeCompilerArgs += "-Xinline-classes" } }
  8. 16.

    Experimental API for Libraries • can be publicly released as

    a part of the library • may break at any moment
  9. 17.

    @ShinyNewAPI class Foo { ... } Experimental API @Experimental annotation

    class ShinyNewAPI You can mark your new class or function as experimental
  10. 22.

    Duration API • KEEP: Duration and Time Measurement API •

    status: experimental in Kotlin 1.3.50 • uses inline classes
  11. 26.

    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! ✓
  12. 29.

    Inline classes: summary • KEEP: inline classes • help to

    improve API and avoid extra allocations • you can go and try it out
  13. 30.
  14. 31.

    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
  15. 32.

    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()
  16. 33.

    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
  17. 34.

    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() } ✓
  18. 36.

    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 } ✓
  19. 37.

    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() } ✓
  20. 38.

    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
  21. 39.

    • 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
  22. 43.

    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
  23. 44.

    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:
  24. 45.

    • 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
  25. 46.
  26. 47.

    Flow • suspend-based reactive stream flow { emit(value) } .map

    { transform(it) } .filter { condition(it) } .catch { exception -> log(exception) } .collect { process(it) }
  27. 50.

    Flows: summary • bring reactive streams to coroutines library •

    currently in an experimental state • will get stable soon
  28. 52.

    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
  29. 54.

    Sharing common code • Sharing business logic • Keeping UI

    platform-dependent • The shared part might vary
  30. 55.

    Common code • you define expect declarations in the common

    code and use them • you provide different actual implementations for different platforms
  31. 56.

    Time measurement example expect fun measureTime(action: () -> Unit): Duration

    Expected platform-specific API: Expected API can be used in the common code: measureTime { // operation }
  32. 57.

    Platform-specific Implementations expect 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
  33. 58.

    Common code • can use the standard library • can

    define expect declarations and use them • can use other multi-platform libraries
  34. 59.

    Multi-platform libraries • Standard library • Ktor HTTP client •

    kotlinx.serialization • kotlinx.coroutines • … and more
  35. 60.

    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
  36. 61.

    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
  37. 63.