Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ContractsでCompilerを賢くしよう / love_kotlin #5
Search
star_zero
October 24, 2018
Programming
670
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ContractsでCompilerを賢くしよう / love_kotlin #5
star_zero
October 24, 2018
More Decks by star_zero
See All by star_zero
今からはじめるAndroidアプリ開発 2024 / DevFest 2024
star_zero
0
1.6k
Jetpack Compose の Side-effect を使いこなす / DroidKaigi 2023
star_zero
5
7.2k
Android 14 新機能 / Android 14 Meetup Nagoya
star_zero
1
690
Android 14 と Predictive back gesture / Shibuya.apk #42
star_zero
0
500
Coroutines Test 入門 / Android Test Night #8
star_zero
2
1.4k
What's new in Jetpack / I/O Extended Japan 2022
star_zero
1
710
Kotlin 2021 Recap / DevFest 2021
star_zero
3
1.4k
Kotlin Symbol Processing (KSP) を使ったコード生成 / DroidKaigi 2021
star_zero
2
5.3k
What's new Android 12
star_zero
0
630
Other Decks in Programming
See All in Programming
ルールを書いて終わらせないハーネスエンジニアリング
yug1224
4
1.8k
jsmini JavaScript Engine を作ってみた話
yosuke_furukawa
PRO
0
290
ソフトウェア設計に溶けるインフラ ― AWS CDK のインフラ認識論
konokenj
3
750
Claude CodeとAgentCore Gatewayを繋ぐ際の認証認可 / Authentication and authorization when connecting Claude Code with AgentCore Gateway
har1101
1
200
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
170
その節約、円になってますか?
isamumumu
1
680
【やさしく解説 設計編・中級 #6】良いアーキテクチャとは ~ 一本の登り道の、行き先 ~
panda728
PRO
0
210
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon-2026
shogogg
0
550
PHP Application における Kubernetes 内 gRPC 通信
ganchiku
0
580
人間の目はかわらない、だからJPEGは30年もつ
yuzneri
12
18k
「人を評価する AI」の設計と実装
ryoyanara
0
150
5分で問診!Composer セキュリティ健康診断
codmoninc
0
860
Featured
See All Featured
Visualization
eitanlees
152
17k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.2k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
340
HDC tutorial
michielstock
2
780
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
440
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
3
1.1k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
660
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.2k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
610
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
360
Transcript
Contractsで Compilerを賢くしよう Kotlin愛好会 vol5
About me •Kenji Abe •Cookpad Inc. •Android Developer •Twitter: @STAR_ZERO
Contracts •Kotlin 1.3の新機能 •関数の動作を明示的にCompilerへ伝える •スマートキャストをより便利に
今回の環境 •IntelliJ IDEA 2018.2.5 •Kotlin 1.3.0-rc-190
簡単な例
Contractsなし fun isNonNull(s: String?): Boolean { return s != null
} fun hoge(s: String?) { if (isNonNull(s)) { // Smart CastされないのでCompile Error println(s.length) } }
Contractsあり @ExperimentalContracts fun isNonNull(s: String?): Boolean { contract { returns(true)
implies (s != null) } return s != null }
Contractsあり @ExperimentalContracts fun hoge(s: String?) { if (isNonNull(s)) { //
Smart Castしてくれる println(s.length) } }
Contractsなし fun runFunc(func: () -> Unit) { func() } fun
hoge() { var x: Int runFunc { x = 10 } // Variable 'x' must be initialized println(x) }
Contractsあり @ExperimentalContracts fun runFunc(func: () -> Unit) { contract {
callsInPlace(func, InvocationKind.EXACTLY_ONCE) } func() }
Contractsあり @ExperimentalContracts fun hoge() { var x: Int runFunc {
x = 10 } // エラーなし println(x) }
returns - implies
returns - implies @ExperimentalContracts fun isNonNull(s: String?): Boolean { contract
{ returns(true) implies (s != null) } return s != null } •戻り値によって決まる引数またはthisの状態を定義
returns - implies •returns() •returns(value: Any?) ‣ true, false, null
•returnsNotNull()
returns - implies •implies ‣ == null, != null ‣
is, !is
Example 1 @ExperimentalContracts fun validate(s: String?) { contract { returns()
implies (s != null) } if (s.isNullOrEmpty()) { throw IllegalArgumentException() } }
Example 1 @ExperimentalContracts fun hoge(value: String?) { validate(value) println("length =
${value.length}") }
Example 2 @ExperimentalContracts fun isString(v: Any?): Boolean { contract {
returns(true) implies (v is String) } return v is String }
Example 2 @ExperimentalContracts fun hoge(v: Any?) { if (isString(v)) {
println("length = ${v.length}") } }
Example 3 @ExperimentalContracts fun castInt(v: Any?): Int? { contract {
returnsNotNull() implies (v is Int) } return v as? Int }
Example 3 @ExperimentalContracts fun hoge(v: Any?) { if (castInt(v) !=
null) { println("${v + v}") } }
Example 4 @ExperimentalContracts fun Any?.isString(): Boolean { contract { returns(true)
implies (this@isString is String) } return this is String }
Example 4 @ExperimentalContracts fun hoge(v: Any?) { if (v.isString()) {
println("length = ${v.length}") } }
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 }
Example 5 @ExperimentalContracts fun hoge(v: Any?) { if (stringOrInt(v)) {
println("length = ${v.length}") } else { println("plus = ${1 + v}") } }
callsInPlace
callsInPlace @ExperimentalContracts fun runFunc(func: () -> Unit) { contract {
callsInPlace(func, InvocationKind.EXACTLY_ONCE) } func() } •引数の関数が何回実行されるか
callsInPlace •AT_MOST_ONCE ‣ 1回実行されるか、呼び出されない •AT_LEAST_ONCE ‣ 1回以上呼び出される •EXACTLY_ONCE ‣ 1回だけ呼び出される
•UNKNOWN ‣ 呼び出される回数が不明
Example 1 @ExperimentalContracts fun runAtLeastOnce(func: () -> Unit) { contract
{ callsInPlace(func, InvocationKind.AT_LEAST_ONCE) } func() }
Example 1 @ExperimentalContracts fun hoge() { var x: Int runAtLeastOnce
{ x = 10 } println(x) }
Example 2 @ExperimentalContracts fun runAtMostOnce(func: () -> Unit) { contract
{ callsInPlace(func, InvocationKind.AT_MOST_ONCE) } func() }
Example 2 @ExperimentalContracts fun hoge() { var x: Int runAtMostOnce
{ x = 10 } // Variable 'x' must be initialized println(x) }
Example 3 @ExperimentalContracts fun runFuncs(func1: () -> Unit, func2: ()
-> Unit) { contract { // func1だけ設定 callsInPlace(func1, InvocationKind.EXACTLY_ONCE) } func1() func2() }
Example 3 @ExperimentalContracts fun hoge() { var x: Int runFuncs({
x = 10 }) { x = 20 } // Variable 'x' must be initialized println(x) }
Example 4 @ExperimentalContracts fun runFuncs(func1: () -> Unit, func2: ()
-> Unit) { contract { // 今度はfunc2だけ設定 callsInPlace(func2, InvocationKind.EXACTLY_ONCE) } func1() func2() }
Example 4 @ExperimentalContracts fun hoge() { var x: Int runFuncs({
x = 10 }) { x = 20 } println(x) }
Example 5 @ExperimentalContracts fun runFunc(func: () -> Unit) { contract
{ callsInPlace(func, InvocationKind.EXACTLY_ONCE) } func() }
Example 5 @ExperimentalContracts fun hoge() { var x: Int runFunc({
x = 10 }) // <- 括弧で括る // Variable 'x' must be initialized println(x) }
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 }
Example 6 @ExperimentalContracts fun hoge(v: Any) { var x: Int
if (complex(v) { x = 10 }) { println("length = ${v.length}") } println("x = $x") }
注意
注意 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関数でしか使えない
まとめ
まとめ •Contractsを使うとComplierがちょっと賢くなる •拡張関数で使うのが現実的な気がする •今後に期待?
ありがとうございました