アプリ開発備忘録

PlayStationMobile、Android、UWPの開発備忘録

Kotlin Contractsが必要な場面に遭遇した

Kotlin Contractsあまり理解していなかったのと、自分で書く必要があるとは思わなかったのでこんな所で使うんだなと思って書きました。

まずこのようなコードがあります。

時間を計測するKotlinのスタンダードライブラリの関数です。

public inline fun measureTimeMillis(block: () -> Unit): Long {
    val start = System.currentTimeMillis()
    block()
    return System.currentTimeMillis() - start
}

使います。

measureTimeMillis {
    getHoge()
}.also { println(it) }

getHoge()で取得した値を外側で使いたいです。
以下のようなコードを書きますがエラーになります。

val hoge : Hoge
measureTimeMillis {
    hoge = getHoge()
}.also { println(it) }

measureTimeMillisの引数のblockが内部で複数回呼ばれる可能性があるからです。

ここでKotlin Contractsを使用します。

@ExperimentalContracts
inline fun measureTimeMillis(block: () -> Unit): Long {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    val start = System.currentTimeMillis()
    block()
    return System.currentTimeMillis() - start
}

blockが一回だけ呼ばれる事を保証してあげます。

これでコンパイルが通ります。