Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ContractsでCompilerを賢くしよう / love_kotlin #5

star_zero
October 24, 2018

ContractsでCompilerを賢くしよう / love_kotlin #5

star_zero

October 24, 2018
Tweet

More Decks by star_zero

Other Decks in Programming

Transcript

  1. Contractsなし fun isNonNull(s: String?): Boolean { return s != null

    } fun hoge(s: String?) { if (isNonNull(s)) { // Smart CastされないのでCompile Error println(s.length) } }
  2. Contractsなし fun runFunc(func: () -> Unit) { func() } fun

    hoge() { var x: Int runFunc { x = 10 } // Variable 'x' must be initialized println(x) }
  3. Contractsあり @ExperimentalContracts fun runFunc(func: () -> Unit) { contract {

    callsInPlace(func, InvocationKind.EXACTLY_ONCE) } func() }
  4. returns - implies @ExperimentalContracts fun isNonNull(s: String?): Boolean { contract

    { returns(true) implies (s != null) } return s != null } •戻り値によって決まる引数またはthisの状態を定義
  5. Example 1 @ExperimentalContracts fun validate(s: String?) { contract { returns()

    implies (s != null) } if (s.isNullOrEmpty()) { throw IllegalArgumentException() } }
  6. Example 2 @ExperimentalContracts fun isString(v: Any?): Boolean { contract {

    returns(true) implies (v is String) } return v is String }
  7. Example 3 @ExperimentalContracts fun castInt(v: Any?): Int? { contract {

    returnsNotNull() implies (v is Int) } return v as? Int }
  8. Example 4 @ExperimentalContracts fun Any?.isString(): Boolean { contract { returns(true)

    implies (this@isString is String) } return this is String }
  9. Example 5 @ExperimentalContracts fun stringOrInt(v: Any?) : Boolean { contract

    { returns(true) implies (v is String) returns(false) implies (v is Int) } return v is String }
  10. Example 5 @ExperimentalContracts fun hoge(v: Any?) { if (stringOrInt(v)) {

    println("length = ${v.length}") } else { println("plus = ${1 + v}") } }
  11. callsInPlace @ExperimentalContracts fun runFunc(func: () -> Unit) { contract {

    callsInPlace(func, InvocationKind.EXACTLY_ONCE) } func() } •引数の関数が何回実行されるか
  12. Example 1 @ExperimentalContracts fun runAtLeastOnce(func: () -> Unit) { contract

    { callsInPlace(func, InvocationKind.AT_LEAST_ONCE) } func() }
  13. Example 2 @ExperimentalContracts fun runAtMostOnce(func: () -> Unit) { contract

    { callsInPlace(func, InvocationKind.AT_MOST_ONCE) } func() }
  14. Example 2 @ExperimentalContracts fun hoge() { var x: Int runAtMostOnce

    { x = 10 } // Variable 'x' must be initialized println(x) }
  15. Example 3 @ExperimentalContracts fun runFuncs(func1: () -> Unit, func2: ()

    -> Unit) { contract { // func1だけ設定 callsInPlace(func1, InvocationKind.EXACTLY_ONCE) } func1() func2() }
  16. Example 3 @ExperimentalContracts fun hoge() { var x: Int runFuncs({

    x = 10 }) { x = 20 } // Variable 'x' must be initialized println(x) }
  17. Example 4 @ExperimentalContracts fun runFuncs(func1: () -> Unit, func2: ()

    -> Unit) { contract { // 今度はfunc2だけ設定 callsInPlace(func2, InvocationKind.EXACTLY_ONCE) } func1() func2() }
  18. Example 5 @ExperimentalContracts fun runFunc(func: () -> Unit) { contract

    { callsInPlace(func, InvocationKind.EXACTLY_ONCE) } func() }
  19. Example 5 @ExperimentalContracts fun hoge() { var x: Int runFunc({

    x = 10 }) // <- 括弧で括る // Variable 'x' must be initialized println(x) }
  20. Example 6 @ExperimentalContracts fun complex(v: Any?, func: () -> Unit):

    Boolean { contract { returns(true) implies (v is String) callsInPlace(func, InvocationKind.EXACTLY_ONCE) } func() return v is String }
  21. Example 6 @ExperimentalContracts fun hoge(v: Any) { var x: Int

    if (complex(v) { x = 10 }) { println("length = ${v.length}") } println("x = $x") }
  22. 注意 class Helper { @ExperimentalContracts fun isNonNull(s: String?): Boolean {

    // Contracts are allowed only for top-level functions contract { returns(true) implies (s != null) } return s != null } } •Top-Level関数でしか使えない