Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Kotlinの関数参照 2017-04-04 Kotlin勉強会@Sansan 長澤 太郎
Slide 2
Slide 2 text
自己紹介 ● たろう @ngsw_taro ● エムスリー株式会社のAndroidエンジニア ● Kotlinエバンジェリスト(自称) ● 著書「Kotlinスタートブック」
Slide 3
Slide 3 text
もくじ 1. 関数参照 2. レシーバが未定のメソッド参照 3. レシーバが確定のメソッド参照 4. プロパティも関数
Slide 4
Slide 4 text
1. 関数参照
Slide 5
Slide 5 text
関数オブジェクト ● Kotlinでは定義済みの関数のオブジェクトを得ること ができる ● 関数オブジェクトを変数に代入したり、別の関数の引 数に渡したり、持ち回して便利に使える。 ● 必ずしもオブジェクトではない(ヒント: インライン関 数)
Slide 6
Slide 6 text
コード例 // 普通の関数 fun succ(n: Int): Int = n + 1 // 関数オブジェクトを取得し、変数に代入 val myFunc: (Int)->Int = ::succ // ^^^^^^^^^^ 関数型 // メソッド呼び出しによる元の関数の計算を実行 myFunc.invoke(5) //=> 6 // 演算子オーバロードによる関数らしい記述 myFunc(7) //=> 8
Slide 7
Slide 7 text
応用例 // 高階関数の引数に「関数参照」を渡す listOf(1, 2, 3).map(::succ) //=> [2, 3, 4] // ラムダ式を使えば同じ listOf(1, 2, 3).map { succ(it) } //=> [2, 3, 4] ● ラムダ式は、文を手続き的に記述していく ● 関数参照は、宣言的な記述になる
Slide 8
Slide 8 text
2. レシーバが未定のメソッド参照
Slide 9
Slide 9 text
メソッド参照 ● メソッドのオブジェクトも取得できる ● この場合は、レシーバが未定 // 「型::メソッド名」という書式で取得 val foo: String.()->String = String::reversed // ^^^^^^^^^^^^^^^^^ 関数型 // メソッドっぽく呼び出せる "Kotlin".foo() //=> niltoK
Slide 10
Slide 10 text
拡張関数もOK fun String.bold(): String = "**$this**" val baz: String.()->String = String::bold "Sansan".baz() //=> **Sansan**
Slide 11
Slide 11 text
普通の関数型にもなるよ ● A.(B)->Cという型は、(A, B)->Cと同じっぽい fun String.bold(): String = "**$this**" // 型どっちでもOK val aaa: String.()->String = String::bold val bbb: (String)->String = aaa // 呼び出し方どっちでもOK "hoge".aaa() //=> **hoge** aaa("fuga") //=> **fuga**
Slide 12
Slide 12 text
高階関数で効果を発揮 "Hello".let { it.bold() } "Hello".let(String::bold) もしString.()->Stringが(String)->Stringと みなせなかったら、2行目の書き方がNGです。
Slide 13
Slide 13 text
3. レシーバが確定のメソッド参照
Slide 14
Slide 14 text
Bound Function Reference ● bound = 束縛された → レシーバが確定してるメソッド参照 ● Kotlin 1.1から使用できる
Slide 15
Slide 15 text
コード例 // 「オブジェクト::メソッド名」の書式で取得 val succ: (Int)->Int = 1::plus succ(5) //=> 6 userRepository.findById(123L) ?.let { user -> user.copy(blocked = true) } ?.let(userRepository::update)
Slide 16
Slide 16 text
4. プロパティも関数
Slide 17
Slide 17 text
プロパティも関数として扱える val prop: KProperty1 = String::length prop.get("Taro") //=> 4 val func: (String) -> Int = prop func("Taro") //=> 4
Slide 18
Slide 18 text
高階関数で効果を発揮 listOf("foo", "wa").map { it.length } // => [3, 2] listOf("foo", "wa").map(String::length) // => [3, 2] もしKProperty1が (String)->Stringとみなせなかったら、2行目の書き 方がNGです。
Slide 19
Slide 19 text
まとめ ● 関数オブジェクトを使うと宣言的な記述ができる ● ::hoge: 関数参照 ● Foo::bar: メソッド参照 ● foo::bar: レシーバ固定メソッド参照 (Bound Function Reference) ● プロパティも関数オブジェクトになれる