What's up next for Kotlin? RC Edition

What's up next for Kotlin? RC Edition

There's probably never been a better moment for the Kotlin ecosystem, and the language is getting ready to become The "write once, run everywhere" solution. Let's walk through some of the features of the upcoming Kotlin release (1.3), to see what the Kotlin future might look like.

3dc29e8cfc6ef333e2b41a1b0e826b57?s=128

Nicola Corti

October 27, 2018
Tweet

Transcript

  1. What’s up next for Kotlin? Nicola Corti @cortinico RC Edition.

  2. 1.3

  3. 1.3

  4. 1.3

  5. Coroutines

  6. Coroutines kotlin { experimental.coroutines = Coroutines.ENABLE }

  7. Coroutines import kotlinx.coroutines.experimental.delay import kotlinx.coroutines.experimental.launch fun justACoroutine() { launch {

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

    delay(1000) println("Hello world!") } }
  9. Capturing When

  10. Capturing When fun Request.getBody() : ResponseBody { val response =

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

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

    { is Authenticator.Success -> response.body is HttpError -> throw HttpException(response.status) }
  13. Capturing When

  14. KEEP

  15. KEEP

  16. Arity

  17. 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) { }
  18. 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"); }
  19. Arity package kotlin.jvm.functions /** A function that takes 0 arguments.

    */ public interface Function0<out R> : Function<R> { /** Invokes the function. */ public operator fun invoke(): R } /** A function that takes 1 argument. */ public interface Function1<in P1, out R> : Function<R> { /** Invokes the function with the specified argument. */ public operator fun invoke(p1: P1): R } /** A function that takes 2 arguments. */ public interface Function2<in P1, in P2, out R> : Function<R> { /** 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<in P1, in P2, in P3, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, out R> : Function<R> {
  20. Arity /** A function that takes 8 arguments. */ public

    interface Function8<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, in P20, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, in P20, in P21, out R> : Function<R> { /** 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<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, in P20, in P21, in P22, out R> : Function<R> { /** 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 }
  21. 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) { }
  22. 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) { }
  23. 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"); }
  24. 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"); }
  25. Arity @SinceKotlin("1.3") interface FunctionN<out R> : Function<R>, FunctionBase<R> { /**

    * 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
  26. Experimental features

  27. Inline Classes

  28. Inline Classes inline class Username(val value: String)

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

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

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

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

    value: String) val myName = Username("nicola") val myPassword = Password("p4ssw0rd") myName = myPassword
  33. 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
  34. 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
  35. Unsigned Types

  36. Unsigned Types val anUnsignedInteger : UInt val anUnsignedLong : ULong

    val anUnsignedByte : UByte val anUnsignedShort : UShort
  37. Unsigned Types val anUnsignedInteger : UInt = 0xFFFF_FFFFu val anUnsignedLong

    : ULong = 10uL val anUnsignedByte : UByte = 0xFFu val anUnsignedShort : UShort = 0xFFFFu
  38. Unsigned Types @SinceKotlin("1.3") @ExperimentalUnsignedTypes public inline class UInt internal constructor(private

    val data: Int) : Comparable<UInt> { bit.ly/keep-utype
  39. Result

  40. Result /** * A discriminated union that encapsulates successful outcome

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

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

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

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

    * with a value of type [T] or a failure with an arbitrary * [Throwable] exception. */ inline class Result<out T> internal constructor( internal val value: Any? // internal value -- either T or Failure ) { internal class Failure(val exception: Throwable) //... } inline fun <R> runCatching(block: () -> R): Result<R>
  45. Result inline fun <R> runCatching(block: () -> R): Result<R> {

    return try { Result.success(block()) } catch (e: Throwable) { Result.failure(e) } }
  46. Result fun findUserByName(name: String): ?

  47. Result fun findUserByName(name: String): Result<User> Not really…

  48. Result fun findUserByName(name: String): User

  49. Result 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
  50. Result fun findUserByName(name: String): User

  51. Result fun findUserByName(name: String): User val result = runCatching {

    findUserByName("...") }
  52. Result - API

  53. Result - Use Cases

  54. Result - Use Cases try { val data = doSomething()

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

    processData(data) } catch(e: Throwable) { showErrorDialog(e) } runCatching { doSomething() } .onFailure { showErrorDialog(it) } .onSuccess { processData(it) }
  56. Result - Use Cases

  57. Result - Use Cases /** * Interface representing a continuation

    after a suspension point that * returns value of type `T`. */ @SinceKotlin("1.3") public interface Continuation<in T> { /** * 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: Result<T>) } bit.ly/keep-result
  58. The Problem

  59. The Problem @Test fun testMyTokenLength() { }

  60. The Problem @Test fun testMyTokenLength() { val token : String?

    = getMyToken(); }
  61. The Problem @Test fun testMyTokenLength() { val token : String?

    = getMyToken(); assertNotNull(token) }
  62. The Problem @Test fun testMyTokenLength() { val token : String?

    = getMyToken(); assertNotNull(token) assertEquals(42, token.length) } Error(5, 22): Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
  63. The Problem @Test fun testMyTokenLength() { val token : String?

    = getMyToken(); assertNotNull(token) assertEquals(42, token?.length) }
  64. Kotlin Contracts • The Compiler is not smart enough to


    understand the context • You know something that the compiler doesn’t know • We can provide this extra knowledge with a Kotlin Contract • The goal is to write better/cleaner code
  65. Syntax

  66. Syntax fun Int?.isValid(): Boolean { return this != null &&

    this != 0 }
  67. Syntax fun Int?.isValid(): Boolean { contract { } return this

    != null && this != 0 }
  68. Syntax fun Int?.isValid(): Boolean { contract { // Place your

    effects here } return this != null && this != 0 }
  69. Effects fun isValid(number: Int?) : Boolean Int? Boolean Effect1, Effect2,

    Effect3
  70. Returns fun returns(): SimpleEffect fun returns(value: Any?): SimpleEffect fun returnsNotNull():

    SimpleEffect interface SimpleEffect : Effect { infix fun implies(boolExpr: Boolean): ConditionalEffect } ConditionalEffect
  71. Syntax fun Int?.isValid(): Boolean { contract { } return this

    != null && this != 0 }
  72. Syntax fun Int?.isValid(): Boolean { contract { returns(true) } return

    this != null && this != 0 }
  73. Syntax fun Int?.isValid(): Boolean { contract { returns(true) implies }

    return this != null && this != 0 }
  74. Syntax fun Int?.isValid(): Boolean { contract { returns(true) implies (this@isValid

    != null) } return this != null && this != 0 }
  75. Syntax val aInt : Int? = getAnInt() if (aInt.isValid()){ }

    else { }
  76. Syntax val aInt : Int? = getAnInt() if (aInt.isValid()){ //

    Here the compiler knows that `aInt` is not nullable // thanks to the contract on `isValid` aInt.absoluteValue } else { }
  77. Syntax val aInt : Int? = getAnInt() if (aInt.isValid()){ //

    Here the compiler knows that `aInt` is not nullable // thanks to the contract on `isValid` aInt.absoluteValue } else { // Here the compiler has no extra information since // the `isValid` has only a `returns(true)` effect aInt?.absoluteValue }
  78. The Problem @Test fun testMyTokenLenght() { val token : String?

    = getMyToken(); assertNotNull(token) assertEquals(42, token?.length) }
  79. The Problem @Test fun testMyTokenLenght() { val token : String?

    = getMyToken(); assertNotNull(token) assertEquals(42, token.length) }
  80. The Problem fun assertNotNull(actual: Any?) { }

  81. The Problem fun assertNotNull(actual: Any?) { org.junit.Assert.assertNotNull(actual) }

  82. The Problem fun assertNotNull(actual: Any?) { contract { returns() implies

    (actual != null) } org.junit.Assert.assertNotNull(actual) }
  83. CallsInPlace • lambda will not be called after the call

    to owner-function is finished. • lambda will not be passed to another function that 
 doesn’t have a similar contract. • lambda will be called the specified amount of times (kind) fun <R> callsInPlace( lambda: Function<R>, kind: InvocationKind = InvocationKind.UNKNOWN ): CallsInPlace
  84. CallsInPlace InvocationKind.UNKNOWN

  85. CallsInPlace InvocationKind.UNKNOWN InvocationKind.AT_MOST_ONCE

  86. CallsInPlace InvocationKind.UNKNOWN InvocationKind.AT_MOST_ONCE InvocationKind.AT_LEAST_ONCE

  87. CallsInPlace InvocationKind.UNKNOWN InvocationKind.AT_MOST_ONCE InvocationKind.AT_LEAST_ONCE InvocationKind.EXACTLY_ONCE

  88. CallsInPlace fun main(){ val x : Int? run { x

    = 10 } println(x) }
  89. CallsInPlace fun main(){ val x : Int? run { x

    = 10 } println(x) } Error:(6, 18) Variable ‘x’ must be initialized Error:(4, 8) Captured values initialization is forbidden due to possible reassignment
  90. CallsInPlace public inline fun <T, R> T.run(block: T.() -> R):

    R { return block() }
  91. CallsInPlace public inline fun <T, R> T.run(block: T.() -> R):

    R { contract { } return block() }
  92. CallsInPlace public inline fun <T, R> T.run(block: T.() -> R):

    R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }
  93. CallsInPlace fun main(){ val x : Int? run { x

    = 10 } println(x) }
  94. Limitations • They are not verified. 
 You’re responsible for

    writing correct contracts. • returns(value) and implies allowed values are limited • Only to top-level and block functions.
  95. 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<T> { fun run(data: T) } val myFunction: Function<String> = { println ("data $it”) } class Foo(var v: Int) immutable class Bar(val foo: Foo) // This should fail bit.ly/kotlin-feature-survey
  96. Thanks! Nicola Corti @cortinico bit.ly/ktcontracts