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. Tokyo Svetlana Isakova @sveta_isakova What’s new in Kotlin?

  2. Kotlin developers 0 750 1500 2250 3000 2016 2017 2018

    156K 700K 2.2M
  3. Timeline … … 2017 Official on Android 2010 Project started

    2016 Kotlin 1.0 2018 Kotlin 1.3
  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!
  5. Agenda • Kotlin evolution • “Experimental” features

  6. Agenda: experimental features • Inline Classes • Contracts • Immutable

    Collections • Flows • Multiplatform Projects
  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
  8. Principles of Pragmatic Evolution • keeping the language modern •

    comfortable updates • feedback loop
  9. KEEPing the language modern https://github.com/Kotlin/KEEP KEEP = Kotlin Evolution and

    Enhancement Process contains language proposals and the corresponding discussions
  10. Comfortable updates • Deprecation warnings in advance • Automatic migration

  11. Feedback loop with the community • Kotlin the community •

    Kotlin team listens to the community • The community members influence the Kotlin evolution
  12. Contributors from all over the world …

  13. Experimental features

  14. Experimental features The goal: to let new features be tried

    by early adopters as soon as possible
  15. Experimental Language Features • you need to explicitly opt in

    at the call site to use experimental features compileTestKotlin { kotlinOptions { freeCompilerArgs += "-Xinline-classes" } }
  16. Experimental API for Libraries • can be publicly released as

    a part of the library • may break at any moment
  17. @ShinyNewAPI class Foo { ... } Experimental API @Experimental annotation

    class ShinyNewAPI You can mark your new class or function as experimental
  18. Using experimental API @UseExperimental(ShinyNewAPI::class) fun doSomethingImportant() { val foo =

    Foo() ... }
  19. • feedback loop for new features and API Experimental: Summary

  20. Inline classes

  21. Inline classes • can wrap values without additional overhead •

    currently an experimental feature
  22. Duration API • KEEP: Duration and Time Measurement API •

    status: experimental in Kotlin 1.3.50 • uses inline classes
  23. Refining API: trying primitive args fun greetAfterTimeout(millis: Long) greetAfterTimeout(2) //

    meaning 2 seconds? Too easy to make a mistake
  24. Refining API: trying overloads fun greetAfterTimeoutMillis(millis: Long) fun greetAfterTimeoutSeconds(seconds: Long)

    greetAfterTimeoutSeconds(2) Too verbose
  25. Refining API: trying class fun greetAfterTimeout(duration: Duration) greetAfterTimeout(Duration(2)) Extra object

    is allocated class Duration(val value: Long)
  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! ✓
  27. Inline classes constraints inline class Duration(val value: Double) fun greetAfterTimeout(duration:

    Duration) inline class can define only one val property
  28. Creating Duration fun greetAfterTimeout(duration: Duration) greetAfterTimeout(2.seconds) ✓ Explicit units in

    the code val Int.seconds get() = toDuration(DurationUnit.SECONDS)
  29. Inline classes: summary • KEEP: inline classes • help to

    improve API and avoid extra allocations • you can go and try it out
  30. Contracts

  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
  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()
  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
  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() } ✓
  35. Kotlin Contracts …allow to share extra information about code semantics

    with the compiler
  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 } ✓
  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() } ✓
  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
  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
  40. Immutable Collections

  41. Standard library: Collections MutableList List read-only

  42. Immutable collections MutableList List ImmutableList PersistentList truly immutable supports modification

    read-only
  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
  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:
  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
  46. Flows

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

    { transform(it) } .filter { condition(it) } .catch { exception -> log(exception) } .collect { process(it) }
  48. Integration with RxJava Use extension functions: • flow.asPublisher() • publisher.asFlow()

  49. Backpressure • Backpressure happens automatically thanks to suspension mechanism

  50. Flows: summary • bring reactive streams to coroutines library •

    currently in an experimental state • will get stable soon
  51. Multi-platform Projects

  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
  53. Multi-platform projects Browser Kotlin/JS Android Kotlin/JVM iOS Kotlin/Native Server Kotlin/JVM

    common code
  54. Sharing common code • Sharing business logic • Keeping UI

    platform-dependent • The shared part might vary
  55. Common code • you define expect declarations in the common

    code and use them • you provide different actual implementations for different platforms
  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 }
  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
  58. Common code • can use the standard library • can

    define expect declarations and use them • can use other multi-platform libraries
  59. Multi-platform libraries • Standard library • Ktor HTTP client •

    kotlinx.serialization • kotlinx.coroutines • … and more
  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
  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
  62. More about Kotlin

  63. None
  64. Kotlin course at Coursera

  65. Hands-on lab “Intro to coroutines & channels” http://kotl.in/hands-on

  66. Have a nice Kotlin!