Slide 1

Slide 1 text

What’s up next for Kotlin? Nicola Corti @cortinico

Slide 2

Slide 2 text

HH

Slide 3

Slide 3 text

A bit of history

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Speakers • Gesh Markov • Christophe Beyls • Niklas Baudy • Cord Jastram • Yahya Bayramoglu • Jossi Wolf • Jendrik Johannes • Ivan Morgillo • Jule Lehmann • Dmitry Zaytsev Lovis Möller - Nicola Corti

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Stats • 7 Meetups organized in the last year • ~280 total attendees • 333 Meetup Members • 128 Twitter Followers • Basically always booked out!

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

pusher.com/state-of-kotlin

Slide 10

Slide 10 text

Kotlin Adoption

Slide 11

Slide 11 text

Migrating Java to Kotlin

Slide 12

Slide 12 text

Reasons for returning to Java Over a quarter of respondents who migrated Java to Kotlin needed to revert.

Slide 13

Slide 13 text

Favorite Features

Slide 14

Slide 14 text

Reasons to use coroutines (or not)

Slide 15

Slide 15 text

1.3

Slide 16

Slide 16 text

1.3-M1 EAP

Slide 17

Slide 17 text

1.3-M1 EAP plugins { kotlin("jvm") version "1.2.60" } repositories { mavenCentral() } dependencies { compile(kotlin("stdlib-jdk8", "1.2.60")) }

Slide 18

Slide 18 text

1.3-M1 EAP plugins { kotlin("jvm") version "1.2.60" } repositories { mavenCentral() maven("http://dl.bintray.com/kotlin/kotlin-eap") } dependencies { compile(kotlin("stdlib-jdk8", "1.2.60")) }

Slide 19

Slide 19 text

1.3-M1 EAP plugins { kotlin("jvm") version "1.3-M1" } repositories { mavenCentral() maven("http://dl.bintray.com/kotlin/kotlin-eap") } dependencies { compile(kotlin("stdlib-jdk8", "1.3-M1")) }

Slide 20

Slide 20 text

1.3-M1 EAP plugins { kotlin("jvm") version "1.3-M1" } repositories { mavenCentral() maven("http://dl.bintray.com/kotlin/kotlin-eap") } dependencies { compile(kotlin("stdlib-jdk8", “1.3-M1")) compile(“org.jetbrains.kotlinx:kotlinx-coroutines-core:0.24.0") }

Slide 21

Slide 21 text

1.3-M1 EAP plugins { kotlin("jvm") version "1.3-M1" } repositories { mavenCentral() maven("http://dl.bintray.com/kotlin/kotlin-eap") } dependencies { compile(kotlin("stdlib-jdk8", “1.3-M1")) compile(“org.jetbrains.kotlinx:kotlinx-coroutines-core:0.24.0-eap13") }

Slide 22

Slide 22 text

Coroutines

Slide 23

Slide 23 text

Coroutines kotlin { experimental.coroutines = Coroutines.ENABLE }

Slide 24

Slide 24 text

Coroutines import kotlinx.coroutines.experimental.delay import kotlinx.coroutines.experimental.launch fun justACoroutine() { launch { delay(1000) println("Hello world!") } }

Slide 25

Slide 25 text

Coroutines import kotlinx.coroutines.delay import kotlinx.coroutines.launch fun justACoroutine() { launch { delay(1000) println("Hello world!") } }

Slide 26

Slide 26 text

Capturing When

Slide 27

Slide 27 text

Capturing When fun Request.getBody() : ResponseBody { val response = executeRequest() when (response) { is Authenticator.Success -> response.body is HttpError -> throw HttpException(response.status) } }

Slide 28

Slide 28 text

Capturing When fun Request.getBody() : ResponseBody { when (val response = executeRequest()) { is Authenticator.Success -> response.body is HttpError -> throw HttpException(response.status) } }

Slide 29

Slide 29 text

Capturing When fun Request.getBody() = when (val response = executeRequest()) { is Authenticator.Success -> response.body is HttpError -> throw HttpException(response.status) }

Slide 30

Slide 30 text

Capturing When

Slide 31

Slide 31 text

Interfaces interface MyPublicApi { }

Slide 32

Slide 32 text

Interfaces interface MyPublicApi { companion object { val baseUrl = "http://..." fun create(): MyPublicApi = ... } }

Slide 33

Slide 33 text

Interfaces interface MyPublicApi { companion object { @JvmField val baseUrl = "http://..." @JvmStatic fun create(): MyPublicApi = ... } } Java 1.8

Slide 34

Slide 34 text

Annotations annotation class MyAnnotation(val value: Int)

Slide 35

Slide 35 text

Annotations annotation class MyAnnotation(val value: Int) { annotation class SubAnnotation }

Slide 36

Slide 36 text

Annotations annotation class MyAnnotation(val value: Int) { annotation class SubAnnotation companion object { val timestamp = System.currentTimeMillis() } }

Slide 37

Slide 37 text

Annotations annotation class MyAnnotation(val value: Int) { annotation class SubAnnotation companion object { @JvmField val timestamp = System.currentTimeMillis() } }

Slide 38

Slide 38 text

KEEP

Slide 39

Slide 39 text

KEEP

Slide 40

Slide 40 text

Arity

Slide 41

Slide 41 text

Arity fun arity22Function(lambda : ( Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit) { }

Slide 42

Slide 42 text

Arity fun arity22Function(lambda : ( Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit) { } public final void arity22Function(@NotNull Function22 lambda) { Intrinsics.checkParameterIsNotNull(lambda, "lambda"); }

Slide 43

Slide 43 text

Arity package kotlin.jvm.functions /** A function that takes 0 arguments. */ public interface Function0 : Function { /** Invokes the function. */ public operator fun invoke(): R } /** A function that takes 1 argument. */ public interface Function1 : Function { /** Invokes the function with the specified argument. */ public operator fun invoke(p1: P1): R } /** A function that takes 2 arguments. */ public interface Function2 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2): R } /** A function that takes 3 arguments. */ public interface Function3 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3): R } /** A function that takes 4 arguments. */ public interface Function4 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4): R } /** A function that takes 5 arguments. */ public interface Function5 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5): R } /** A function that takes 6 arguments. */ public interface Function6 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6): R } /** A function that takes 7 arguments. */ public interface Function7 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7): R } /** A function that takes 8 arguments. */ public interface Function8 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8): R } /** A function that takes 9 arguments. */ public interface Function9 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9): R } /** A function that takes 10 arguments. */ public interface Function10 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10): R } /** A function that takes 11 arguments. */ public interface Function11 : Function {

Slide 44

Slide 44 text

Arity /** A function that takes 8 arguments. */ public interface Function8 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8): R } /** A function that takes 9 arguments. */ public interface Function9 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9): R } /** A function that takes 10 arguments. */ public interface Function10 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10): R } /** A function that takes 11 arguments. */ public interface Function11 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11): R } /** A function that takes 12 arguments. */ public interface Function12 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12): R } /** A function that takes 13 arguments. */ public interface Function13 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13): R } /** A function that takes 14 arguments. */ public interface Function14 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14): R } /** A function that takes 15 arguments. */ public interface Function15 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15): R } /** A function that takes 16 arguments. */ public interface Function16 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16): R } /** A function that takes 17 arguments. */ public interface Function17 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17): R } /** A function that takes 18 arguments. */ public interface Function18 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18): R } /** A function that takes 19 arguments. */ public interface Function19 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19): R } /** A function that takes 20 arguments. */ public interface Function20 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20): R } /** A function that takes 21 arguments. */ public interface Function21 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21): R } /** A function that takes 22 arguments. */ public interface Function22 : Function { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21, p22: P22): R }

Slide 45

Slide 45 text

Arity fun arity22Function(lambda : ( Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit) { }

Slide 46

Slide 46 text

Arity fun arity23Function(lambda : ( Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit) { }

Slide 47

Slide 47 text

Arity fun arity23Function(lambda : ( Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit) { } public final void arity23Function(@NotNull FunctionN lambda) { Intrinsics.checkParameterIsNotNull(lambda, "lambda"); }

Slide 48

Slide 48 text

Arity fun arity23Function(lambda : ( Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit) { } public final void arity23Function(@NotNull FunctionN lambda) { Intrinsics.checkParameterIsNotNull(lambda, "lambda"); }

Slide 49

Slide 49 text

Arity @SinceKotlin("1.3") interface FunctionN : Function, FunctionBase { /** * Invokes the function with the specified arguments. * * Must **throw exception** if the length of passed [args] * is not equal to the parameter count returned by [arity]. * * @param args arguments to the function */ operator fun invoke(vararg args: Any?): R /** * Returns the number of arguments that must be passed to * this function. */ override val arity: Int } http://bit.ly/keep-bigarity

Slide 50

Slide 50 text

Experimental features

Slide 51

Slide 51 text

Inline Classes

Slide 52

Slide 52 text

Inline Classes inline class Username(val value: String)

Slide 53

Slide 53 text

Inline Classes inline class Username(val value: String) typealias Username = String

Slide 54

Slide 54 text

Inline Classes inline class Username(val value: String) inline class Password(val value: String)

Slide 55

Slide 55 text

Inline Classes inline class Username(val value: String) inline class Password(val value: String) val myName = Username("nicola") val myPassword = Password("p4ssw0rd")

Slide 56

Slide 56 text

Inline Classes inline class Username(val value: String) inline class Password(val value: String) val myName = Username("nicola") val myPassword = Password("p4ssw0rd") myName = myPassword

Slide 57

Slide 57 text

Inline Classes inline class Username(val value: String) inline class Password(val value: String) val myName = Username("nicola") val myPassword = Password("p4ssw0rd") myName = myPassword myPassword = myName

Slide 58

Slide 58 text

Inline Classes inline class Username(val value: String) inline class Password(val value: String) val myName = Username("nicola") val myPassword = Password("p4ssw0rd") myName = myPassword myPassword = myName myName = "MyNewName" bit.ly/keep-inlineclasses

Slide 59

Slide 59 text

Unsigned Types

Slide 60

Slide 60 text

Unsigned Types val anUnsignedInteger : UInt val anUnsignedLong : ULong val anUnsignedByte : UByte val anUnsignedShort : UShort

Slide 61

Slide 61 text

Unsigned Types val anUnsignedInteger : UInt = 0xFFFF_FFFFu val anUnsignedLong : ULong = 10uL val anUnsignedByte : UByte = 0xFFu val anUnsignedShort : UShort = 0xFFFFu

Slide 62

Slide 62 text

Unsigned Types @SinceKotlin("1.3") @ExperimentalUnsignedTypes public inline class UInt internal constructor(private val data: Int) : Comparable { bit.ly/keep-utype

Slide 63

Slide 63 text

Experimental Annotations

Slide 64

Slide 64 text

Experimental Annotations @Experimental(Experimental.Level.WARNING) annotation class MyCoolFeatureExperimental

Slide 65

Slide 65 text

Experimental Annotations @Experimental(Experimental.Level.WARNING) annotation class MyCoolFeatureExperimental @MyCoolFeatureExperimental fun myExperimentalFunction() { // ... }

Slide 66

Slide 66 text

Experimental Annotations @Experimental(Experimental.Level.WARNING) annotation class MyCoolFeatureExperimental @MyCoolFeatureExperimental fun myExperimentalFunction() { // ... } @UseExperimental(MyCoolFeatureExperimental::class) fun myClientCode() { myExperimentalFunction() }

Slide 67

Slide 67 text

Experimental Annotations @Experimental(Experimental.Level.WARNING) annotation class MyCoolFeatureExperimental @MyCoolFeatureExperimental fun myExperimentalFunction() { // ... } @UseExperimental(MyCoolFeatureExperimental::class) fun myClientCode() { myExperimentalFunction() } bit.ly/keep-experimental

Slide 68

Slide 68 text

SuccessOrFailure

Slide 69

Slide 69 text

SuccessOrFailure /** * A discriminated union that encapsulates successful outcome * with a value of type [T] or a failure with an arbitrary * [Throwable] exception. */ inline class SuccessOrFailure internal constructor( internal val value: Any? // internal value -- either T or Failure ) { internal class Failure(val exception: Throwable) //... }

Slide 70

Slide 70 text

SuccessOrFailure /** * A discriminated union that encapsulates successful outcome * with a value of type [T] or a failure with an arbitrary * [Throwable] exception. */ inline class SuccessOrFailure internal constructor( internal val value: Any? // internal value -- either T or Failure ) { internal class Failure(val exception: Throwable) //... }

Slide 71

Slide 71 text

SuccessOrFailure /** * A discriminated union that encapsulates successful outcome * with a value of type [T] or a failure with an arbitrary * [Throwable] exception. */ inline class SuccessOrFailure internal constructor( internal val value: Any? // internal value -- either T or Failure ) { internal class Failure(val exception: Throwable) //... }

Slide 72

Slide 72 text

SuccessOrFailure /** * A discriminated union that encapsulates successful outcome * with a value of type [T] or a failure with an arbitrary * [Throwable] exception. */ inline class SuccessOrFailure internal constructor( internal val value: Any? // internal value -- either T or Failure ) { internal class Failure(val exception: Throwable) //... } inline fun runCatching(block: () -> R): SuccessOrFailure

Slide 73

Slide 73 text

SuccessOrFailure /** * A discriminated union that encapsulates successful outcome * with a value of type [T] or a failure with an arbitrary * [Throwable] exception. */ inline class SuccessOrFailure internal constructor( internal val value: Any? // internal value -- either T or Failure ) { internal class Failure(val exception: Throwable) //... } inline fun runCatching(block: () -> R): SuccessOrFailure

Slide 74

Slide 74 text

SuccessOrFailure inline fun runCatching(block: () -> R): SuccessOrFailure { return try { SuccessOrFailure.success(block()) } catch (e: Throwable) { SuccessOrFailure.failure(e) } }

Slide 75

Slide 75 text

SuccessOrFailure fun findUserByName(name: String): ?

Slide 76

Slide 76 text

SuccessOrFailure fun findUserByName(name: String): SuccessOrFailure You can do better…

Slide 77

Slide 77 text

SuccessOrFailure fun findUserByName(name: String): User

Slide 78

Slide 78 text

SuccessOrFailure sealed class FindUserResult { data class Found(val user: User) : FindUserResult() data class NotFound(val name: String) : FindUserResult() data class MalformedName(val name: String) : FindUserResult() // other cases that need different business-specific handling code } fun findUserByName(name: String): FindUserResult

Slide 79

Slide 79 text

SuccessOrFailure fun findUserByName(name: String): User

Slide 80

Slide 80 text

SuccessOrFailure fun findUserByName(name: String): User val result = runCatching { findUserByName("...") }

Slide 81

Slide 81 text

SuccessOrFailure fun findUserByName(name: String): User fun findUserByNameCatching(name: String): SuccessOrFailure val result = runCatching { findUserByName("...") }

Slide 82

Slide 82 text

SuccessOrFailure - Use Cases

Slide 83

Slide 83 text

SuccessOrFailure - Use Cases fun readFilesCatching(files: List): List> = files.map { }

Slide 84

Slide 84 text

SuccessOrFailure - Use Cases fun readFilesCatching(files: List): List> = files.map { runCatching { readFile(it) } }

Slide 85

Slide 85 text

SuccessOrFailure - Use Cases fun readFilesCatching(files: List): List> = files.map { runCatching { readFile(it) } } readFilesCatching(listOf("...")).map { }

Slide 86

Slide 86 text

SuccessOrFailure - Use Cases fun readFilesCatching(files: List): List> = files.map { runCatching { readFile(it) } } readFilesCatching(listOf("...")).map { result -> }

Slide 87

Slide 87 text

SuccessOrFailure - Use Cases fun readFilesCatching(files: List): List> = files.map { runCatching { readFile(it) } } readFilesCatching(listOf("...")).map { result : SuccessOrFailure -> }

Slide 88

Slide 88 text

SuccessOrFailure - Use Cases fun readFilesCatching(files: List): List> = files.map { runCatching { readFile(it) } } readFilesCatching(listOf("...")).map { result -> result.mapCatching { formatFile(it) } }

Slide 89

Slide 89 text

SuccessOrFailure - Use Cases fun readFilesCatching(files: List): List> = files.map { runCatching { readFile(it) } } readFilesCatching(listOf("...")).map { result -> result.mapCatching { formatFile(it) } }

Slide 90

Slide 90 text

SuccessOrFailure - Use Cases

Slide 91

Slide 91 text

SuccessOrFailure - Use Cases try { val data = doSomething() processData(data) } catch(e: Throwable) { showErrorDialog(e) }

Slide 92

Slide 92 text

SuccessOrFailure - Use Cases try { val data = doSomething() processData(data) } catch(e: Throwable) { showErrorDialog(e) } runCatching { doSomething() } .onFailure { showErrorDialog(it) } .onSuccess { processData(it) }

Slide 93

Slide 93 text

SuccessOrFailure - Use Cases

Slide 94

Slide 94 text

SuccessOrFailure - Use Cases /** * Interface representing a continuation after a suspension point that * returns value of type `T`. */ @SinceKotlin("1.3") public interface Continuation { /** * Context of the coroutine that corresponds to this continuation. */ public val context: CoroutineContext /** * Resumes the execution of the corresponding coroutine passing successful or failed [result] as the * return value of the last suspension point. */ public fun resumeWith(result: SuccessOrFailure) } bit.ly/keep-successorfailure

Slide 95

Slide 95 text

To infinity… • Collections Literals • SAM Conversion • Truly Immutability val list = listOf("1", "2", "3") val list = ["1", "2", "3"] val map = mapOf("1" to 1, "2" to 2, "3" to 3) val map = ["1" = 1, "2" = 2, "3" = 3] interface Function { fun run(data: T) } val myFunction: Function = { println ("data $it”) } class Foo(var v: Int) immutable class Bar(val foo: Foo) // This should fail bit.ly/kotlin-feature-survey

Slide 96

Slide 96 text

Thanks! Nicola Corti @cortinico