第67回Kotlin dojoを開催した

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

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

 

前回の様子はコチラ↓ 

kdnakt.hatenablog.com

 

 

[第67回の様子]

2021/6/9に第67回を開催した。

 

今週はちょっとメンバーが減って、自分をいれて3名だった。

今週は自分がドライバをつとめようと思ったけど、MacBookが不調のため断念してナビゲータ役で参加。

最近Web会議をやろうとするとMacBookのファンがうるさいことが多い。M1の16インチ出てくれないかな...13インチで我慢すべきか...。

 

勉強会本編の内容としては、Kotlin/Native Concurrencyハンズオンの続きを実施した。第3章のつづきをすべて終わらせた。

 

[学んだことや疑問点]

  • Kotlin/Native Concurrency: 3. Frozen State
    • 先週うごかせなかったAm I Frozen?の動作確認。
fun freezeSomeState(){
    val sd = SomeData("Hello 🐶", 22)
    // 比較のため以下の行を追加
    println("Am I frozen? ${sd.isFrozen}") // false
    sd.freeze()

    println("Am I frozen? ${sd.isFrozen}") // true
}
    • つぎの例はこれ。Frozenな値を変更しようとするとどうなるか……
fun failChanges(){
    val smd = SomeMutableData(3)
    smd.i++
    println("smd: $smd")

    smd.freeze()
    smd.i++              // 例外が発生する
    println("smd: $smd") // ここにはたどりつけない
}

data class SomeMutableData(var i:Int)
    • なお発生する例外は以下の通り
Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen sample.SomeMutableData@7dc0df58
        at 0   KNConcurrencySamples.kexe           0x0000000104d2bb67 kfun:kotlin.Throwable.(kotlin.String?)kotlin.Throwable + 87 (/Users/teamcity1/teamcity_work/4d622a065c544371/runtime/src/main/kotlin/kotlin/Throwable.kt:22:37)
        at 1   KNConcurrencySamples.kexe           0x0000000104d26075 kfun:kotlin.Exception.(kotlin.String?)kotlin.Exception + 85 (/Users/teamcity1/teamcity_work/4d622a065c544371/runtime/src/main/kotlin/kotlin/Exceptions.kt:23:44)
        at 2   KNConcurrencySamples.kexe           0x0000000104d26175 kfun:kotlin.RuntimeException.(kotlin.String?)kotlin.RuntimeException + 85 (/Users/teamcity1/teamcity_work/4d622a065c544371/runtime/src/main/kotlin/kotlin/Exceptions.kt:34:44)
        at 3   KNConcurrencySamples.kexe           0x0000000104d4b2b5 kfun:kotlin.native.concurrent.InvalidMutabilityException.(kotlin.String)kotlin.native.concurrent.InvalidMutabilityException + 85 (/Users/teamcity1/teamcity_work/4d622a065c544371/runtime/src/main/kotlin/kotlin/native/concurrent/Freezing.kt:22:60)
(以下略)
    • 新しい例外InvalidMutabilityExceptionがここで登場する。最初はイライラするかもしれないが、すぐに慣れるよ、とのこと。まあたしかにNullPointerExceptionよりは原因が特定しやすいかも。freeze()を探せばいいはずなので。
    • 前回気になっていたfreeze() freezes everything it touchesという表現については、プロパティ全て、ということらしい。以下の例を参照。

fun freezeChildren(){ val dataWithReference = DataWithReference(SomeData("Hello 🐶", 22)) dataWithReference.freeze() println("Am I frozen? ${dataWithReference.child.isFrozen}") // true } data class DataWithReference(val child:SomeData)

    • ここで気になったのは、プロパティにthisを代入した場合にfreeze()は無限ループするのか?という問題。以下のコードで試してみたところ、通常すぐに結果が返ってきていたのに、30秒ほど待っても結果が返ってこなかったのでどうやら無限ループする模様。しかし、freeze()を呼び出したからというよりはプロパティにthisを持たせようとした時点でだめっぽい。難しい...
fun failChanges(){
    val smd = SomeMutableData2(3, null)
    println("smd1: $smd") // 出力された
    smd.i++
    println("smd2: $smd") // 出力された
    smd.smd = smd // ここで無限ループする?
    println("smd3: $smd") // ここが出力されなかった

    smd.freeze() // ここまでたどりついていない
    smd.i++ // InvalidMutabilityException例外が発生する?
}

 data class SomeMutableData2(var i:Int, var smd:SomeMutableData2?)

 

[まとめ]

モブプログラミング・スタイルで、Kotlin/Native Concurrencyハンズオンを進めた。

freeze()とInvalidMutabilityExceptionは少しわかった気がする。Kotlin(あるいはKotlin/Native)のプロパティで自己参照が危険そうなのもわかった。

 

今週のプルリクエストはこちら。

github.com