kdnakt blog

hello there.

第51回Kotlin dojoを開催した

今週は第51回を開催しました!

引き続きKotlin Hands-onをすすめています。

 

前回の様子はコチラ↓

kdnakt.hatenablog.com

 

 

[第51回の様子]

2021/2/10に第51回を開催した。

 

参加メンバーは自分をいれて3名。

前回のつづきの内容があったので、自分が連続してドライバーを担当した。

 

勉強会本編の内容としては、前回に続いてIntroduction to Coroutines and Channelsハンズオンを進めた。第2章の最後の部分を読んで、第3章の演習問題のタスクを1つ実施した。

 

[学んだことや疑問点]

  • Introduction to Coroutines and Channels: 2. Blocking request
    • 前回やったタスクの解答を見ていく
    • 自分たちの書いたコードは以下のようになっていた
fun List<User>.aggregate() =
    this.groupBy { it.login }
        .mapValues { it.value.sumBy { user -> user.contributions } }
        .toList()
        .map { User(it.first, it.second) }
        .sortedByDescending { it.contributions }
    • 模範解答として掲載されていたコードは以下のようになっていた
fun List<User>.aggregate(): List<User> =
    groupBy { it.login }
        .map { (login, group) -> User(login, group.sumBy { it.contributions }) }
        .sortedByDescending { it.contributions }
    • 自分の理解が追いつかなかったが、参加者に解説してもらったところによると、自分たちのコードの方が計算量が少なくなっている、らしい。
    • 別の解答としてgroupByではなく、groupingBy関数を利用することもできる

groupingBy - Kotlin Programming Language

// groupingBy() の利用例
val words = "one two three four five six seven eight nine ten".split(' ')
val frequenciesByFirstChar = words.groupingBy { it.first() }.eachCount()
println("Counting first letters:")
println(frequenciesByFirstChar) // {o=1, t=3, f=2, s=2, e=1, n=1}

val moreWords = "eleven twelve".split(' ')
val moreFrequencies = moreWords.groupingBy { it.first() }.eachCountTo(frequenciesByFirstChar.toMutableMap())
println(moreFrequencies) // {o=1, t=4, f=2, s=2, e=2, n=1}
    • groupingByのほうが便利そうに見えるので、覚えておきたい
  • Introduction to Coroutines and Channels: 3. Using callbacks
    • 第3章では、コールバックを利用してGitHub APIの呼び出し部分を別スレッドに移すことで、UIメインスレッドを解放し、UIのフリーズを回避していく
    • SwingUtilities.invokeLaterをコールバック内で呼び出すことで、別スレッドからUIを更新する部分を実現できる
    • タスク:BACKGROUNDモードで読み込みを行うと、UIはフリーズしないが、結果が画面に表示されない。これを修正せよ
    • よくよく手元のソースコードを読んでみると、コールバックが呼び出されていないという衝撃の実装だった
fun loadContributorsBackground(service: GitHubService, req: RequestData,
        updateResults: (List<User>) -> Unit) {
    thread {
        loadContributorsBlocking(service, req)
    }
} 
    • loadContributorsBlocking()の戻り値の型がList<User>であり、コールバックの引数と同じなので、シンプルにコールバックを利用するように修正する
fun loadContributorsBackground(service: GitHubService, req: RequestData,
        updateResults: (List<User>) -> Unit) {
    thread {
        updateResults(loadContributorsBlocking(service, req))
    }
} 
    • 今回は流石に模範解答と一致した。

 

[まとめ]

モブプログラミング・スタイルで、Introduction to Coroutines and Channelsハンズオンを進めた。

またしても新しいCollection関連の関数groupingByを学んだ。Collection奥が深い。

そしてCoroutineいつ出てくるんだ……。

 

今週の進捗は以下のプルリクエストにまとまっている。

github.com