Kotlin 1.3.70の変更点

※ソース記事は[こちら](https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-3-70-released/)
※Kotlin/JSやKotlin/Nativeについては個人的に使っていないので、割愛します。

# 標準ライブラリの変更
追加された新しい機能は実験的な状態であることに注意。
## 共通ライブラリのStringBuilderの拡張
StringBuilderはすでに標準ライブラリ、`kotlin.text`パッケージにあるが、多くの重要なメンバは無いか、JVMでのみ利用可能だった。現在は、JVMのすべてのStringBuilder機能は共通のexpect classに追加され、それぞれのプラットフォーム上で対応する実装を持つ。これはすべての必要なメンバがそこにあるため、共通コードから`StringBuilder`を効果的に使用することができることを意味する。

## KClassとの連携
KClassについての基本的に有用なメンバは、kotlin-reflectへの依存が不要になった。
```Kotlin
import kotlin.reflect.cast

@OptIn(ExperimentalStdlibApi::class)
fun main() {
val kClass = String::class
println(kClass.simpleName) // String
println(kClass.qualifiedName) // kotlin.String

println(kClass.isInstance("abc")) // true
println(kClass.isInstance(10)) // false
println(kClass.cast("abc")) // abc
}
```
以前は、動作させるため、実行時にKotlinのリフレクションの実装を提供する必要があった。
今では追加の依存関係無しで、これらのシンプルなメンバーを使用することができる。

## 実験的アノテーションを改名(@Experimentalと@UseExperimental)
ご存じかもしれないが、Kotlinには[実験的機能を使用するためのメカニズム](https://kotlinlang.org/docs/reference/experimental.html)が備わっている。それは標準ライブラリからのアノテーションを含む。それは自身が実験的であるか、他の実験的宣言を使用することの印を宣言につける。以前のバージョンではそれらは、`@UseExperimental`と`@Experimental`だった。
このメカニズムのスコープを広げることが決定された。なぜなら実験的状態であるものは、APIを使うために同意を必要とする唯一の理由ではないためである。例えば、あるAPIは内部向けであるとか、いくつか制約があるといったことがありうる。これを反映させるため、アノテーションを改名した。@UseExperimentalと@Experimentが@OptInと@RequiresOptInに変更された。したがってコンパイラ引数の-Xuse-experimentalも、-Xopt-inに変更された。-Xexperimentalについては、まれにしか使わず、複雑になるので、削除されている。@UseExperimentalと@Experimentalは1.3.70ではまだサポートされるが、1.4にて削除する予定である。
## 時間計測APIの改名
もう一つの重要な改名は、[期間と時間計測API](https://blog.jetbrains.com/kotlin/2019/08/kotlin-1-3-50-released/#time-measurement-api)である。`Clock`と`ClockMark`は`TimeSource`と`TImeMark`にそれぞれ改名された。以前の名前は非推奨の型エイリアスとして維持されている。
e)
## ArrayDeque - 両端キューの実装
[両端キュー](https://en.wikipedia.org/wiki/Double-ended_queue)の実装である、`kotlin.collections.ArrayDeque`クラスが標準ライブラリに追加されたことをうれしく思う。コミュニティから何度か要求されていた。たとえJava標準ライブラリのjava.util.ArrayDequeが使えるとしても、Kotlin/JS、Kotlin/Nativeのために使える共通の実装が無く、重要なのは共通のコードに無いことだった。現在は、実験的状態とはいえ、そのような実装が利用可能である。
両端キューは、償却定数時間で、キューの先端・末端両方向から要素を追加・削除可能である。
```Kotlin
@OptIn(ExperimentalStdlibApi::class)
fun main() {
val deque = ArrayDeque(listOf(1, 2, 3))

deque.addFirst(0)
deque.addLast(4)
println(deque) // [0, 1, 2, 3, 4]

println(deque.first()) // 0
println(deque.last()) // 4

deque.removeFirst()
deque.removeLast()
println(deque) // [1, 2, 3]
}
```
キューやスタックがコードで必要になったら、デフォルトで両端キューを使うことができる。
`kotlin.collections.ArrayDeque`の実装は、可変長のArrayをベースに使い、循環バッファであるArrayの中に中身を入れ、一杯になった時だけ、リサイズする。
コンセプトとしては、`ArrayDeque`の実装は`java.util.ArrayDeque`にととても良く似ている。しかし注意点として別の実装であり、この新しい実装は、Kotlin/JVMのためにこのクラスを使うときに使われる。この違いは、次のように他のCollectionと連携するときに現れる。`ArrayList`を生成しJVMでコンパイルすると、実際は`java.util.ArrayList`が使われる。Javaの`ArrayDeque`が`Collection`インターフェイスのみを実装しているのと異なり、Kotlinの`ArrayDeque`は`MutableList`を実装している。このことはインデックスですべての要素にアクセスでき、JavaのArrayDequeでは不可能である。
ArrayDequeクラスは現状は実験的状態でリリースされており、フィードバックを楽しみにまっている。

## Collectionビルダー
もう一つの重要な機能は、コレクションのためのbuilder関数、つまり`buildList`、`buildSet`、`buildMap`である。builder関数を使うことで、生成の間は変更可能なコレクションを便利に操作し、結果として読み取り専用のコレクションを得ることができる。
```Kotlin
@OptIn(ExperimentalStdlibApi::class)
fun main() {
val needsZero = true
val initial = listOf(2, 6, 41)

val ints = buildList { // this: MutableList
if (needsZero) {
add(0)
}
initial.mapTo(this) { it + 1 }
}
println(ints) // [0, 3, 7, 42]
}
```
これらのbuilder関数は、buildStringと似たように実装されている。buildListは引数として一つのレシーバーを持つラムダ関数を取る。ラムダ関数の中の暗黙のthisレシーバーは、MutableListの型を持ち、buildListは戻り値として読み取り専用のListを返却する。
builder関数を使うことは、条件を使ったり、いくつかの初期状態のコレクションを変更したり、結果をマージしたりといった複雑な操作を行う必要があるときに、パフォーマンス面で度々読みやすく効果的である。これらの関数は現状実験的状態でリリースされることに注意すること。
## reduceOrNullとrandomOrNull対応物
Kotlinの規約として、`string.toInt()`と`string.toIntOrNull()`のように、関数のペア、一つは操作ができないなら例外を投げるもの、もう一つはnullを返却するものがある。今回新しく、対応物として`randomOrNull()`と`reduceOrNull()`関数が同じ規約にしたって追加された。

```Kotlin
@OptIn(ExperimentalStdlibApi::class)
fun main() {
val list = listOf(1, 2, 3)
println(list.randomOrNull()) // 1 or 2 or 3
println(list.reduceOrNull { a, b -> a + b }) // 6

val emptyList = emptyList<Int>()
println(emptyList.randomOrNull()) // null
println(emptyList.reduceOrNull { a, b -> a + b }) // null
}
```
もし`ramdon()`や`reduce()`を使うなら、コレクションが空の場合は例外が発生するだろう。
## scan()関数
リストとシーケンスに連携する新しい一連の関数が追加されている。それらは「スキャン」の概念を意味し、似たような関数は、異なる[ライブラリ](http://reactivex.io/documentation/operators/scan.html)や[言語](https://docs.python.org/3/library/itertools.html#itertools.accumulate)にすでに存在する。
`scan()`は`fold()`に密接に関連している。`scan()`も`fold()`もどちらも一連の値への二値の操作を適用するが、`fold()`が最終的な結果を返却するのに対して、`scan()`は中間結果のシーケンスを返却する。
```Kotlin
@OptIn(ExperimentalStdlibApi::class)
fun main() {
val ints = (1..4).asSequence()
println(ints.fold(0) { acc, elem -> acc + elem }) // 10

val sequence = ints.scan(0) { acc, elem -> acc + elem }
println(sequence.toList()) // [0, 1, 3, 6, 10] ここでscan処理が行われる
}
```
もし結果の型が要素の型と同じであり、初期値として最初の要素を使うことができるのなら、`reduce()`と`scanReduce()`が使うことができる。
留意すべきは、シーケンスにおいて`scan()`と`scanReduce()`を使うときは、それらは結果としてシーケンスを返却するが、本来の性質として遅延が行われる。このことは、scanの結果のsequenceからデータを問い合わせるとき、具体的には、例えば、`toList()`や`max()`といった、(他のシーケンスでない何かを返却する)最終的な操作を呼ぶときに、`scan()`の処理が始まることを意味する。リストにおいて`scan()`と`scanReduce()`を使うときは、結果としてリストが返却される。
# intelliJ IDEAサポート(※割愛)
# Kotlin/JVM
Kotlinは今はJVMバイトコード(version1.8+ターゲット)内に型アノテーションを生成するため、実行時に使うことができる。この特徴は何度かコミュニティによって要求があった。なぜなら、既存のJavaライブラリをより簡単に扱うことができ、新しいライブラリを作るうえで強力なためである。
以下の例では、String上の@Fooアノテーションは、バイトコードに出力され、ライブラリコードにより使うことができる。
```Kotlin
@Target(AnnotationTarget.TYPE)
annotation class Foo

class A {
fun foo(): @Foo String = "OK"
}
```
バイトコードに型アノテーションを出力するには、次の手順にしたがうこと。
- 宣言したアノテーションが、適切なアノテーション対象(JavaのElementType.TYPE_USEかKotlinのAnnotationTarget.TYPE)とretention(AnnotationRetention.RUTIME)であることを確認する。
- クラス宣言のアノテーションとアノテーションを使うコード両方が、JVMバイトコードのターゲットバージョンが1.8以上でコンパイルする。コンパイラオプションで-jvm-target=1.8で指定できる。
- アノテーションを使うコードを-Xemit-jvm-type-annotationsコンパイラオプションでコンパイルする。
注意すべきは、標準ライブラリからの型アノテーションは、ターゲットバージョン1.6でコンパイルされているため、現状、バイトコードには出力されない。
今のところ、以下の基本的なケースのみサポートされている。
- メソッドパラメータ、戻り値、プロパティ型の型アノテーション
- 不変な型引数の射影 例えば`Smth<@Ann Foo>, Array<@Ann Foo>`

※)不変とは、上記例でFooそのものの型であり、Fooの基底クラスや派生クラスは不可。それらを許可することは共変や反変という。
将来的には 共変や反変の型射影の型アノテーションや、インナー型のアノテーション(`Smth<@Ann Outer.Inner>`のようなもの)のサポートを計画している。サポートされているケースですでにほぼ、実世界のシナリオをカバーしていると信じているが、もしより複雑なケースで型アノテーションが必要ならば、教えてほしい。
# 更新方法
いつも通り、[こちら]()でオンラインでKotlinを試すことができる。
- **GradleとMaven**: コンパイラと標準ライブラリのためのバージョンとして`1.3.70`を使用すること。[Gradle用](http://kotlinlang.org/docs/reference/using-gradle.html)と[Maven用](https://kotlinlang.org/docs/reference/using-maven.html)のドキュメントを参照のこと。
- **IntelliJ IDEAとAndroid Studio**: Kotlinプラグインのバージョンを1.3.70に更新すること。*ツール/Kotlin/Kotlinプラグインの更新の構成*を使い、「再度チェックする」ボタンをクリックすること。
- **Eclipse**: [MarketPlace](https://marketplace.eclipse.org/content/kotlin-plugin-eclipse)を使ってプラグインをインストールすること。
- **コマンドラインコンパイラ**:[Github リリースページ]からダウンロードすることができる。
もし、新しいリリースで問題に遭遇したら、Slack([ここ](http://slack.kotlinlang.org/)で招待を得る)の[フォーラム](https://discuss.kotlinlang.org/)で自由に質問するか、[issue tracker](https://youtrack.jetbrains.com/issues/KT)で問題を報告することができる。