今週は第67回を開催しました!
引き続きKotlin Hands-onをすすめています。
前回の様子はコチラ↓
[第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)のプロパティで自己参照が危険そうなのもわかった。
今週のプルリクエストはこちら。