クリスマスプレゼントにはKotlin1.1が欲しいです

この投稿は **Retty inc. Advent Calendar** 17日目の記事です．
昨日はSatoshi Nishinaka氏(@satoshi_nishinaka)の[Let's Enjoy PhantomJS](http://qiita.com/satoshi_nishinaka/items/eb78d9a74b35d98dbb4e)でした．

皆さんこんにちは．Retty inc.のSakataです．Kotlinの1.0が[リリースされた](https://blog.jetbrains.com/kotlin/2016/02/kotlin-1-0-released-pragmatic-language-for-jvm-and-android/)2016年も残すところあと二週間となりました．先月の末，Kotlin 1.1の三番目のマイルストーンリリース，1.1-M03がありましたね．皆さんはもう試しましたか？今回はこの1.1-M03とKotlin 1.1の機能の一つであるcoroutineのプロトタイプ，[kotlinx.coroutines](https://github.com/Kotlin/kotlin-coroutines)を実際に使いながらただでさえかわいいKotlinが1.1で更に魅力的になるのを楽しみたいと思います．

# はじめに
この記事は[Kotlin Blog](https://blog.jetbrains.com/kotlin/)をもとにKotlin1.1-M03の時点で利用することができる機能をかんたんにまとめたものです．

>This is not a stable version of Kotlin, and no compatibility guarantees are given here: in the future previews of 1.1, syntax, APIs, command-line switches and anything else may be changed. If you need a stable version of Kotlin, please stay on 1.0.X until further notice.

[引用元](https://blog.jetbrains.com/kotlin/2016/07/first-glimpse-of-kotlin-1-1-coroutines-type-aliases-and-more/)

ということで後々ここで紹介したサンプルコードは**動かなくなるかもしれません．**引用したソースコードは明記しています．


# 準備

まずはIDEAでKotlin1.1とkotlinx.corutinesを使えるようにします．gradleプロジェクトを作成してこんな感じに設定します．

```groovy:build.gradle
group 'io.github.yusaka39'
version '1.0-SNAPSHOT'

buildscript {
    ext.kotlin_version = '1.1-M03'

    repositories {
        mavenCentral()
        maven { url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1' }
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

apply plugin: 'kotlin'
apply plugin: 'application'

mainClassName = 'io.github.yusaka39.demos110.MainKt'

repositories {
    mavenCentral()
    maven { url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1' }
    maven { url "http://dl.bintray.com/kotlin/kotlinx.coroutines" }
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    compile 'org.jetbrains.kotlinx:kotlinx-coroutines-generate:0.1-alpha-2'
    compile 'org.jetbrains.kotlinx:kotlinx-coroutines-async:0.1-alpha-2'
    compile 'org.jetbrains.kotlinx:kotlinx-coroutines-rx:0.1-alpha-2'
}
```

また，[Tools] -> [Kotlin] -> [Configure Kotlin Plugin Updates] から EAP 1.1 を選んでpluginをアップデートしておくとIDEのサポートが効いて楽ちんです．

# 新しい文法

まずは文法レベルでの変更を紹介したいと思います．

## 型エイリアス

いわゆる型シノニムです．既存の型に別名をつけることができます．

```kotlin
typealias Point = Pair<Double, Double>

fun square(x: Double) = x * x
fun calcDistance(from: Point, to: Point): Double {
    val (fromX, fromY) = from
    val (toX, toY) = to
    return Math.sqrt(square(toX - fromX) + square(toY - fromY))
}
```

今回の例だと`Point`を拡張して下のように`x`と`y`をプロパティとして宣言できますが，適切にスコープを切らないと`Pair<Double, Double>`にも宣言されて(あくまでもただの同義語)キモいので注意が必要です．

```kotlin
val Point.x: Double
    get() = this.first
val Point.y: Double
    get() = this.second

(0.0 to 0.0).x // legal
```

## インスタンスからメンバ参照

今までも`HogeClass::method`でクラスのメソッドを参照することができましたが，`instanceOfHoge::method`でレシーバがバインドされたメソッドを得ることができるようになりました．

```kotlin
val fruits = listOf("apple", "orange", "peach")
fruits.filter("apple"::equals) // ["apple"]
```

## ローカルなdelegated property
classのメンバ以外の場所でもdelegated propertyが使えるようになりました．Androidっぽいコードで失礼します．

```kotlin:HogeActivity.kt
class HogeActivity : AppCompatActivity() {

    @Suppress("unchecked_cast")
    fun <T> bindView(resId: Int) = lazy {
        this.findViewById(resId) as T
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        this.setContentView(R.layout.hoge)
        val titleText: TextView by bindView(R.id.titleText)
        titleText.text = "hello"
    }
}
```

今までdelegateしたいがためにクラスのプロパティとして宣言していたもののスコープが絞れてハッピーな感じです．

## lambdaでdataな引数を分解

今までも下のようなコードはリーガルでした．

```kotlin
data class Triple<F, S, T>(val first: F, val second: S, val third: T)

fun sum(triple: Triple<Int, Int, Int>): Int {
    val (f, s, t) = triple
    return f + s + t
}
```

1.1-M03では次のようなコードも許容されます．

```kotlin
val lst: List<Triple<Int, Int, Int>> = // Some initialize codes
lst.map { (f, s, t) -> f + s + t }
```

## 変数宣言でアンスコ

データクラスを分解したり複数の引数を取るlambdaを使うケースで使わない変数をgolangとかっぽく`_`にできるようになりました．

```kotlin
val lst: List<Pair<Hoge, Fuga>> = // Some initialize codes
lst.forEach { (_, fuga) -> doSomethingWithFuga(fuga) }

val (hoge, _) = lst.filterIndexed{ i, _ -> i % 2 == 0 }[0]
```

:innocent:try-catchでもつかえます(使うのが妥当かどうかは置いといて):innocent:

```kotlin
try {
    executeQuery(query)
} catch (_: SqlException) {
    // Ignore
}
```

## 数値でアンスコ

数値リテラルの中にアンスコを書いて桁区切りしたりできるようになりました．

```
10_000_000 // legal
23_57 // legal
23__57 // legal
23_57.0 // legal
23_57f // legal
0x2_357 // legal

_2357 // illegal
2357_ // illegal
```

# stdlib

便利な子が増えました．

## Enum向けジェネリック関数

reifiedな型変数からenumのvalueやvaluesを取ってこれるトップレベル関数
`enumValues()`，`enumValueOf()`が生えました．

## DSL開発用にスコープをタイトにするやつ

今までは次のようなケースが起こりうる問題がありました．

```kotlin
table {
  tr {
    tr {} // PROBLEM: Table.tr() is valid here
  }
}
```
[コード引用元](https://blog.jetbrains.com/kotlin/2016/11/kotlin-1-1-m03-is-here/)

これはhtmlビルダの例ですが，`tr`(outer)の中に`tr`(inner)は入ってほしくないが`tr`(outer)から`table`のコンテキストが見えてしまうため，Kotlinの文法的に合法に`tr`(inner)が呼び出せてしまいます．これの問題を解決するために`@DslMarker`アノテーションが追加されました．このアノテーションで注釈されたアノテーションで注釈されたクラスから同じアノテーションがついているクラスのコンテキストが見えなくなります．~~自分で書いてて訳がわからなくなってきた．~~簡単なhtmlビルダの例を示します．

アノテーションなしの場合

```kotlin
fun html(initializer: Html.() -> Unit) = Html(initializer)

class Html(initializer: Html.() -> Unit) {
    lateinit var header: Header
    init {
        this.initializer()
    }

    fun header(initializer: Header.() -> Unit) {
        this.header = Header(initializer)
    }
}

class Header(initializer: Header.() -> Unit) {
    init {
        this.initializer()
    }
}

html {
    // this@Htmlが見えている
    header {
        // this@Headerとthis@Htmlが見えている
        header { // legal
        }
    }
}
```

アノテーション有りの場合

```kotlin
@DslMarker
annotation class HtmlMarker

fun html(initializer: Html.() -> Unit) = Html(initializer)

@HtmlMarker
class Html(initializer: Html.() -> Unit) {
    lateinit var header: Header
    init {
        this.initializer()
    }

    fun header(initializer: Header.() -> Unit) {
        this.header = Header(initializer)
    }
}

@HtmlMarker
class Header(initializer: Header.() -> Unit) {
    init {
        this.initializer()
    }
}

html {
    // this@Htmlが見えている
    header {
        // this@Headerが見えている
        header { // Html#header()が見えないのでillegal
        }
    }
}
```

[kotlinx.html repository](https://github.com/Kotlin/kotlinx.html)でも使っているようです．

# Coroutine

コルーチンがKotlinにくる！

すでに独自の実装を生み出している人とか居そうですが最終的にstdlibに入ってくるようです．

## async/await

```kotlin
fun getRestaurant(id: Long) = CompletableFuture.supplyAsync {
    // 通信が入る処理
}

fun getRestaurantsById(ids: List<Long>) = async<List<Restaurant>> {
    ids.map { getRestaurant(it) } // 通信を並列で実行
            .map { await(it) } // 通信がすべて完了したらidに対応する順にListに突っ込む
}

fun showRestaurants(ids: List<Long>) = asyncUI {
    await(getRestaurantsById(ids)).let {
        setRestaurantsToView(it) // 非同期で待機しつつ終わったらUIスレッドでViewを操作
    }
}
```

イイね！

## yield
iterableなsomethingの生成を簡単にしてくれるイケてる奴です．見かけ上無限のものも作れます．型が許す限り正しいフィボナッチ数列になるものを生成してみます．

```kotlin
fun fib() = generate<Long> {
    var acc1 = 0L
    var acc2 = 1L
    while (true) {
        yield(acc1)
        val tmp = acc1
        acc1 = acc2
        acc2 += tmp
    }
}

(0 until 10).zip(fib().asIterable())
// [(0, 0), (1, 1), (2, 1), (3, 2), (4, 3), (5, 5), (6, 8), (7, 13), (8, 21), (9, 34)]
```

ちなみに下の例は怒られます．

```kotlin
fun fib() = generate<Long> {
    tailrec fun iter(acc1: Long, acc2: Long) {
        yield(acc1)
        iter(acc2, acc1 + acc2)
    }
    iter(0L, 1L)
}
```

# まとめ

Kotlinを書いててできたら良いなと思っていたあんな機能やこんな機能が盛り込まれててStableのリリースが待ち遠しいですね！

# 参考にしたもの
- [Kotlin Blog](https://blog.jetbrains.com/kotlin/)
- [Kotlin repository](https://github.com/JetBrains/kotlin)
- [kotlinx.coroutines repository](https://github.com/Kotlin/kotlinx.coroutines)
- [kotlinx.html repository](https://github.com/Kotlin/kotlinx.html)