New Type Inference and Related Language Features Svetlana Isakova Svetlana Isakova has worked on the Kotlin language at JetBrains. She’s co-authored the book Kotlin in Action and now is a Developer Advocate, where she spends her time teaching Kotlin and speaking at conferences worldwide.
Kotlin Puzzler Kotlin1.2で実行する場合 fun main(args: Array) { var hoge: Int? run { hoge = 46 } println(hoge) } // a) 46 // b) NullPointerException // c) null // d) Will not compile
Kotlin Puzzler Kotlin 1.3より前では実行出来ない fun main(args: Array) { var hoge: Int? run { hoge = 46 } println(hoge) } // a) 46 // b) NullPointerException // c) null // d) Will not compile
Kotlin Puzzler fun main(args: Array) { var hoge: Int? run { hoge = 46 } println(hoge) } // a) 46 // b) NullPointerException // c) null // d) Will not compile コンパイラは初期化されているのか、判断出来ない
New type inference • SAM conversions for Kotlin functions • Better inference for builders • Better inference for call chains • Better inference for intersection types
SAM conversions val obs = Observable.just(100) Observable.just(1) .zipWith(obs, BiFunction { a, b -> a + b }) .subscribe { } RxJava2から第二引数でlamda式が使えなくなっていた => RxKotlin(https://github.com/ReactiveX/RxKotlin) で回避していた
Inference for builder lambdas fun buildList( init: MutableList.() -> Unit ): List { return mutableListOf().apply(init) } fun main() { val list = buildList { add(1) add(2) } } もちろん自分でも定義可能
Inference for builder lambdas @UseExperimental(ExperimentalTypeInference::class) fun buildList( @BuilderInference init: MutableList.() -> Unit ): List { return mutableListOf().apply(init) } fun main() { val list = buildList { add(1) add(2) } } BuilderInference annotationを使う
Inference for builder lambdas @UseExperimental(ExperimentalTypeInference::class) fun buildList( @BuilderInference init: MutableList.() -> Unit ): List { return mutableListOf().apply(init) } fun main() { val list = buildList { add(1) add(2) } } BuilderInference annotationを使う
Inference for builder lambdas @UseExperimental(ExperimentalTypeInference::class) fun buildList( @BuilderInference init: MutableList.() -> Unit ): List { return mutableListOf().apply(init) } fun main() { val list = buildList { add(1) add(2) } } これによって1.3より前で
Inference for builder lambdas @UseExperimental(ExperimentalTypeInference::class) fun buildList( @BuilderInference init: MutableList.() -> Unit ): List { return mutableListOf().apply(init) } fun main() { val list = buildList { add(1) add(2) } } Intを省略可能
Inference for call chains fun createMap(): Map = MapBuilder() .put("answer", 42) .build() MapBuilderは自分で定義した関数? (発表資料ままです) Kotlin 1.2: One call is analyzed at a time Kotlin 1.3: A call chain is analyzed
Intersection types interface Foo interface Bar fun hoge(thing: T) where T : Foo, T : Bar { println(thing) } fun better() { val something: Better = Better.A if (something is Foo && something is Bar) { hoge(something) // Foo & Bar } } sealed class Better { object A : Better() object B : Better(), Foo object C : Better(), Foo, Bar }
Intersection types interface Foo interface Bar fun hoge(thing: T) where T : Foo, T : Bar { println(thing) } fun better() { val something: Better = Better.A if (something is Foo && something is Bar) { hoge(something) // Foo & Bar } } sealed class Better { object A : Better() object B : Better(), Foo object C : Better(), Foo, Bar }
Intersection types interface Foo interface Bar fun hoge(thing: T) where T : Foo, T : Bar { println(thing) } fun better() { val something: Better = Better.A if (something is Foo && something is Bar) { hoge(something) // Foo & Bar } } sealed class Better { object A : Better() object B : Better(), Foo object C : Better(), Foo, Bar } somethingは Foo & Barと判定しているが…
Intersection types interface Foo interface Bar fun hoge(thing: T) where T : Foo, T : Bar { println(thing) } fun better() { val something: Better = Better.A if (something is Foo && something is Bar) { hoge(something) // Compile error } } sealed class Better { object A : Better() object B : Better(), Foo object C : Better(), Foo, Bar } Kotlin1.2まではコンパイルエラーだった
Intersection types interface Foo interface Bar fun hoge(thing: T) where T : Foo, T : Bar { println(thing) } fun better() { val something: Better = Better.A if (something is Foo && something is Bar) { hoge(something) // Foo & Bar } } sealed class Better { object A : Better() object B : Better(), Foo object C : Better(), Foo, Bar } 1.3からはコンパイル可