Kotlin 1.3.70リリースの紹介

2020年3月3日に公開されたKotlin 1.3.70リリースブログポストの翻訳です。

kotlin_1370

この増分リリースでは、重要な新機能は提供していません。 ただし、既存機能の改善と問題修正に最善を尽くし、さらには実験的機能も追加して皆さんにお試し頂けるようにしています。 Kotlin 1.3.70のハイライトは次のとおりです。

  • 標準ライブラリのKotlinコレクションに新しい関数とクラスが追加されました。
  • *.gradle.ktsのサポート、テスト、デバッグ、補完の改善など、IntelliJ Kotlinプラグインにさまざまな改善を実施しました。
  • Kotlin/JVMコンパイラがJava 8以降のターゲットに対してバイトコード内に型の注釈を生成できるようになりました。
  • バンドルの最適化、npmの依存関係宣言、および待ち望まれていたKotlin/JSの新しいドキュメントに対応しました。
  • Kotlin/Nativeのコンパイルとデバッグが高速化されました。
  • IDEおよびコマンドラインツールでのスクリプト作成対応が強化されました。

完全な変更リストは変更ログで確認できます。 毎度のことながら、外部貢献者の皆さんに感謝いたします。

それでは詳しく見ていきましょう!

 

標準ライブラリの変更

標準ライブラリに追加された新しい関数はすべて実験的な状態(experimental state)であることにご注意ください。

共通ライブラリのStringBuilderを拡張

StringBuilderはすでにkotlin.textパッケージ内の共通標準ライブラリに存在します。 しかし、多くの重要なメンバーは存在しないか、JVMでしか利用できませんでした。 今回、全JVMのStringBuilder機能が、各種プラットフォームに対応する実装と共に共通のexpect classに追加されました。 つまり、必要なメンバーすべてがそこにあるため、一般的なコードからStringBuilderを効率よく使うことができます。

KClassの操作

KClassの基本的かつ便利なメンバーの一部が、JVMのkotlin-reflect依存関係を必要としなくなりました。

以前はKotlinリフレクションの実装を提供し、それを動作させる必要がありました。 今回のリリースにより、依存関係を追加することなく単純なメンバーを使用できるようになりました。

実験的注釈(@Experimentalおよび@UseExperimental)の名前変更

ご存じのとおり、Kotlinには実験的機能を使用する仕組みが組み込まれています。 このような仕組みには、実験的宣言または他の実験的宣言を使用する宣言をマークする標準ライブラリの注釈が含まれます。 旧バージョンでは、@UseExperimental@Experimentalが注釈に使用されていました。

APIを使用するための同意が必要なのは実験的な状態にあるものだけとは限らないため、この仕組みの範囲を広げることにしました。 例えば、APIには内部でのみ利用可能なものや、制限があるものがあります。 このような状況を反映するため、注釈の名前を変更しました。結果的に名前@OptIn@RequiresOptIn@UseExperimental@Experimentalを置き換えました。 コンパイラの引数「-Xuse-experimental」が「-Xopt-in」に名前変更されました。 「-Xexperimental」は使用頻度が非常に低く、非常に複雑化しているので廃止しました。 古い宣言である@Experimental@UseExperimentalは引き続き1.3.70でもサポートされていますが、1.4では廃止される予定です。

実験的な時間測定APIの名前変更

今回行ったもう一つの名前変更は、Duration and Time measurement API(期間と時間測定API)に関するものです。 それに応じてClockClockMarkTimeSourceTimeMarkに名前変更されました。 以前の名前は非推奨の型エイリアスとして保存されています。

両端キューの実装:ArrayDeque

両端キューの実装であるkotlin.collections.ArrayDequeクラスをKotlin標準ライブラリに追加しました! この実装はこれまで長らくコミュニティから求められていたものです。 Java標準ライブラリのjava.util.ArrayDequeクラスを使用することもできましたが、Kotlin/JSやKotlin/Native、そして何よりも一般的なコードで使用できる一般的な実装は存在しませんでした。 今回のリリースでは、実験的ではありますがこのような実装を利用できるようになりました。

両端キューを使用すると、一定の償却時間内にキューの先頭と末尾の両方に要素を追加・削除できます。

コード内にキューやスタックが必要な場合、デフォルトで両端キューを使用できます。

kotlin.collections.ArrayDequeの実装は裏側で動的配列を使用しており、その内容を循環バッファであるArrayに保存し、このArrayがいっぱいになったときだけ大きさを変更します。

ArrayDequeの実装は概念上、java.util.ArrayDequeの実装に非常によく似ています。 ただし、これらは別の実装であり、Kotlin/JVMにこのクラスを使用すると新しい実装が使用されることに注意してください。 これは他のコレクションとの動作とは異なり、ArrayListを作成してそれをJVMにコンパイルすると、java.util.ArrayListクラスが内部的に使用されます。 Collectionインターフェースを実装するJavaのArrayDequeとは異なり、KotlinのArrayDequeMutableListを実装します。 つまり、インデックスですべての要素にアクセスできるということです。これはJavaのArrayDequeでは不可能です。

紺藍はArrayDequeクラスを実験的な状態でリリースしています。皆さんのご意見をお待ちしています!

コレクションビルダー

もう一つの重要な新機能は、コレクション用のビルダー関数(buildListbuildSetbuildMap)です。 作成フェーズでこのようなビルダー関数を使用してミュータブルなコレクションを便利に操作し、読み込み専用コレクションを結果として取得することができます。

これらのビルダー関数はbuildStringと同様に実装されています。 buildListはレシーバを含むラムダを引数に取ります。 ラムダ内の暗黙的な “this” レシーバは型MutableListを持ちますが、buildListは読み込み専用のListを結果として返します。

条件の使用、複数の初期コレクションの変更、結果のマージといった複雑な操作を実行する必要がある場合、ビルダー関数を使用すると往々にして可読性が向上し、パフォーマンスの点でより効率が上がります。 現在、これらの関数も実験的な状態でリリースされています。

reduceOrNull()およびrandomOrNull()対照関数

Kotlinにはstring.toInt()string.toIntOrNull()のように、片方が演算不可能な場合には例外をスローし、もう片方はnullを返す関数のペアを持たせるという規則があることをご存じかと思います。 同じ規則に従って、新しいrandomOrNull()およびreduceOrNull()のペアとなる関数を追加しました。

random() および reduce()を使用すると、コレクションが空の場合に例外が発生します。

scan() 関数

リストとシーケンスを処理するための新しい関数セットを追加しています。 これらは「スキャニング」の概念を表すもので、同様の関数はすでに別のライブラリ言語に存在します。

scan()fold() と密接に関連しています。 scan()fold() はどちらも値のシーケンスに所定の二項演算を適用します。ただし、scan() が中間結果のシーケンス全体を返すのに対して fold() は最終結果のみを返すという点が異なります。

foldのように、scanは最初のアキュムレータ値を取得します。

結果の型が要素の型と同じで最初の要素を初期値として使用できる場合、reduce() および scanReduce() 関数を使用できます。

シーケンスで scan()scanReduce() を使用した場合は結果としてシーケンスが返されますが、本質的には遅延します。 つまり、スキャンプロセスは結果シーケンスからデータを要求したときだけ、具体的にはtoList()max()のような終端操作(別のシーケンス以外の何かを返すもの)を呼び出したときだけ開始します。 リストで scan()scanReduce() を使用した場合はリストが結果として返されます。

詳細については、こちらのKEEPをお読みください。

IntelliJ IDEAの対応

このリリースでは、IntelliJ IDEAのKotlin対応に関する複数の改善が行われています。 その中でも特に重要なものをご紹介します。

*.gradle.kts 対応

1.3.70ではIntelliJ IDEAのGradle Kotlin DSLスクリプト(*.gradle.ktsファイル)対応を改善しました。 その結果、最新バージョンのKotlinプラグインではシンタックスハイライト、補完、検索、およびKotlinビルドスクリプトの処理に関するその他要素のパフォーマンスが改善されました。 詳細な改善のレビューは、こちらのブログ投稿に記載しています。
すべての変更や改善によるメリットを受けるには、IntelliJ IDEA 2019.2以降とGradle 6.0以降を使用するようにしてください。

コード補完

1.3.70では、IntelliJ IDEAのKotlinコード補完を大幅に改善しています。 このリリースでは、拡張関数、オブジェクトレベルのオーバーライドなどのオブジェクト内で宣言された関数のほか、ネストされたオブジェクト内で宣言された関数も補完候補に含まれるようになりました。

オブジェクト拡張の補完

また、補完リストを並べ替える機械学習モデルも改善し、最も関連性の高いオプションが一番上に表示されるようにしました。

新しいカラースキーム

エディタでKotlinコードの外観をお好みに合わせて変更できるよう、カスタマイズ可能な新しいカラースキームを追加しました。 具体的には、suspendの関数呼び出しとプロパティ宣言に独自のカラースキームを設定できるようになりました。
suspendのカラースキーム

デバッグの改善

旧バージョンのKotlin/Nativeデバッグにはブレークポイントの種類が複数存在していたため、どのブレークポイントを使用すべきかといったといった迷いが生じる原因となっていました。 一種類のブレークポイント「Kotlin Line Breakpoint」をJVMとNativeの各ターゲットに使用できるようになりました。

Kotlin/JSとKotlin/Nativeのテスト

Kotlin/JSとKotlin/Nativeのテスト結果が、Kotlin/JVMのテストと同様にIntelliJ IDEAの右側に表示されるようになりました。 さらに、Kotlin/JSのテストフィルタを修正して個別テストを実行できるようにしました。また、iOSシミュレータをターゲットとするKotlin/Nativeテストをついに「Play」ボタンを押して直接起動できるようにしました。

さらに、IntelliJ IDEA Ultimateではテスト宣言近くのアイコンをクリックしてKotlin/JSのデバッグを起動できます。

または、GradleツールウィンドウでnodeRunnodeTestbrowserTestのいずれかのタスクを手動で選択してデバッグを起動することもできます。 browserRunの場合は、Attach to Node.js/Chrome実行構成を使用して開発サーバーを起動した後にデバッガを接続できます。

その他の注目すべき改善

他にもIntelliJ IDEAのKotlin対応に関する改善が行われています。 ここでは言及する価値のあるものを紹介します。

  • ファイル解析とコピーペースト操作のパフォーマンスを改善しました。
  • 無意味な単項演算子に対応した新しいインスペクションを追加しました。 このインスペクションは長い式を複数行に分割する際に表示される場合があります。
    未使用の単項演算子
  • 呼び出しチェーン、改行、スペース、コメントのフォーマットを含むさまざまなフォーマットを改善しました。

Kotlin/JVM

KotlinはJVMバイトコード(ターゲットバージョン1.8以降)で型の注釈(type annotation)を生成し、それを実行時に利用できるようになりました。 この機能は一部の既存Javaライブラリをはるかに使いやすくし、新しいライブラリの作成者をより強力に支援するため、コミュニティから長らく要望があがっていました。

以下の例では、String 型の @Foo 注釈をバイトコードに出力してライブラリコードで使用できます。

型の注釈をバイトコードに出力するには、以下の手順に従ってください。

  • 宣言した注釈に適切な注釈対象(JavaのElementType.TYPE_USEまたはKotlinのAnnotationTarget.TYPE)と保存設定(AnnotationRetention.RUNTIME)があることを確認してください。
  • 注釈クラスの宣言とその注釈を使用するコード(上記の例ではクラスA)の両方をJVMバイトコードターゲットバージョン1.8以上にコンパイルします。 これは -jvm-target=1.8 コンパイラオプションで指定できます。
  • -Xemit-jvm-type-annotations コンパイラオプションで注釈を使用しているコードをコンパイルします。

標準ライブラリの型の注釈はターゲットバージョン1.6でコンパイルされているため、現在はバイトコードに出力されていないことにご注意ください。

今までのところ、基本的なケースのみがサポートされています。

  • メソッドのパラメータ、メソッドの戻り値の型、プロパティの型に対する型の注釈。
  • 型引数の不変(Invariant)な投影(Projection)(Smth<@Ann Foo>Array<@Ann Foo>など)。

今後、共変(covariant)および反変(contravariant)な型投影と内部型(inner type)(Smth<@Ann Outer.Inner>など)の注釈に対する型注釈の生成に対応する予定です。 サポートされているケースはすでにほとんどの実際のシナリオに対応していると考えていますが、より複雑なケースで型注釈が必要な場合はお知らせください。

Kotlin/JS

Kotlin 1.3.70では、JavaScriptターゲットにバンドルサイズの点で複数の大幅な最適化が行われ、依存ファイル、リソース、およびテストの処理方法関して作業品質を改善するいくつかの変更が行われています。 また、ターゲットのドキュメントを全面的に改訂しました。

バンドルの最適化

Kotlin 1.3.70からはDCE(Dead Code Elimination、デッドコード削除)が org.jetbrains.kotlin.js Gradle プラグインから簡単に使用できるようになり、手動で追加する必要がなくなりました。 また、JSプロジェクトの最適化と実行を制御するのに使用できる新しいタスク一式が実装されました。

開発中はbrowserDevelopmentRunを使用してバンドルされた開発サーバーで最適化されていないアプリケーションの実行を開始し、browserDevelopmentWebpackを使用してbuild/distributionsフォルダ内に最適化されていないアプリケーションのバンドルを作成します。 最適化を一切実行しない場合はより高速にビルドされますが、コンパイルされたプログラムのファイルサイズが大きくなります。

本番の準備をする際は、browserProductionRunを使用して最適化されたアプリケーションの実行を開始し、browserProductionWebpackを使用して本番でのデプロイに適した最適化されたバンドルを生成します。 本番ビルドのコンパイルには若干時間がかかりますが、最終的には開発ビルドよりも大幅に最適化されたバンドルになります。

プロジェクト 開発ビルド(gzip) 本番ビルド(gzip)
“Hello, World” 963 KiB 14 KiB
Kotlin/React Example(“CodeQuiz”) 4.1 MiB 345 KiB

以前のGradleタスクであるbrowserRun(現在はbrowserDevelopmentRunのエイリアス)とbrowserWebpack(現在はbrowserProductionWebpackのエイリアス)は引き続き使用できますが、ビルドスクリプトのいずれかに新たに追加された同等のタスクと置き換える必要があります。

これらのGradleタスクは、multiplatform または kotlin.js Gradleプラグインを使用するプロジェクトで利用できます。 kotlin.jsの場合、より短い形式のタスクエイリアス(browserDevelopmentRun用のrunbrowserProductionWebpack用のbuild)を使用することもできます。

Kotlin/JSのデッドコード削除とその微調整方法に関する詳細を知るには、ドキュメントをチェックしてください。

リソースの自動コピー

distributionsフォルダにバンドルを作成するビルドタスク(browserProductionWebpackなど)がresourcesフォルダから全アセットをコピーするようになったため、デプロイ可能なアーティファクト一式を取得するために画像、スタイルシートその他を手動でコピーする必要がなくなりました。

よりスムーズなnpmの依存関係宣言対応

Kotlin/JS Gradleプラグインを使用する際、npmの依存関係をメインのソースセットに手動で追加する代わりに最上位の依存関係ブロック内で宣言できるようになりました。 つまり、以下のようなスニペットが有効になりました。

Gradle経由の実験的なテストのデバッグ

IntelliJ IDEAからKotlin/JSブラウザをターゲットとするテストを直接デバッグできるようになりました。 不合格になったテストをデバッグするには、IDEでブレークポイントを設定し、デバッグモードでcheck Gradleタスクを開始するか、ガターアイコンを使用してテストセットをデバッグしてください。 Gradleはプラットフォーム用のテストタスクを実行し、デバッガは合成のブレークポイントで停止します。 GradleがコンソールにbrowserTestタスクを表示するとすぐにブレークポイントにヒットします。

この時点でデバッガの「:browserTest」セッションに切り替え、「Debugger」というラベルのタブを選択します。 「Resume Program」ボタンをクリックすると、テストの実行が開始します。

jsデバッグ

現在、この手順はIntelliJ IDEAのデバッガとJSエンジンとの同期を維持するために必要です。 私たちはこのデバッグセッションの開始手順が多すぎることを認識していますので、今後のバージョンでよりスムーズにデバッグできるようになるまでお待ちください!

また、残っている課題のいくつかを解決した後にNode.jsをターゲットとするKotlinコードのデバッグについても同様の対応を行う予定です。

ドキュメントの改善

Kotlin 1.3.70では、JavaScriptターゲット向けのドキュメントとチュートリアルに待ち望まれていた変更を加えています。これにより、Kotlin/JSに使い始められるようになることを願っています。 ドキュメントを最新の内容に更新し、古い内容を削除しました。 また、ウェブサイトに簡易形式のチュートリアル一式を新たに追加しました。これらのチュートリアルでは、Kotlin/JSで作業する際に直面する可能性のある典型的なタスクの要点を説明しています。 また、Kotlin/JS Gradleプラグインを使い始めるのに役立ち、JavaScriptターゲットのアプリケーションをビルドする際の典型的なタスクに対応しています。 ハンズオンコース「ReactとKotlin/JSを使用したウェブアプリケーションの構築」も更新され、Gradle用のKotlin/JSプラグインの使い方を学習できるようになりました。

これらの変更によって、Kotlin/JSを特にフロントエンド開発に試したいとお考えの方が簡単に作業を開始できるようになることを願っています。 私たちは皆さんのKotlin/JSの学習を支援するドキュメントや参考資料を常に改善するよう努めています。 そのため、ドキュメントやハウツーに重要な情報がまだ足りない場合は、コメントでお知らせください。

Kotlin/Native

パフォーマンスの最適化

1.3.70では、Kotlin/Nativeの開発プロセス全体に対するパフォーマンス最適化作業の結果を初めて公開します。 コンパイル時間のパフォーマンスはKotlin/Nativeの弱点の一つであることは周知の事実でしたので、コンパイル時間を短縮するための2つの新機能を実装しました。

  • Kotlin/NativeのコンパイラがGradleデーモンから直接起動するようになったため、コンパイルのたびに新しいプロセスを起動してコンパイラをそのプロセスに読み込む時間がかからなくなりました。
  • デバッグモードでは、コンパイラがプロジェクトの依存関係をキャッシュします。 初回コンパイルにかかる時間は少し長くなりましたが、その後のコンパイルは高速に完了します。 ただし、この機能はiOSシミュレータ(iosX64)とmacOS(macosX64)のみで有効であり、まだ開発中です。

ランタイムとデバッグのパフォーマンス改善も忘れずに実施しています。 1.3.70では、オブジェクト割り当ての時間を若干削減しています。その結果、1つのスタックにより多くのオブジェクトを割り当てられるようになり(ヒープ割り当てよりも高速)、一部のシングルトンオブジェクトがコンパイル時に作成されるようになりました。 デバッグプロセスも高速化されました。

単体アプリケーションで複数のKotlinフレームワークに対応

以前はランタイムで定義されたObj-Cクラスが競合しており、ランタイムの異なるインスタンスに由来していたため、1つのアプリケーションが複数の動的Kotlin/Nativeフレームワークを使用できないという既知の問題がありました。 1.3.70ではこの問題が修正されているため、1つのアプリケーション複数のKotlin/Nativeフレームワークを使用できるようになりました。 共通の依存関係はすべて、異なるSwiftモジュール(および異なるObj-Cプレフィックス)配下のフレームワークに存在します。

vector型の対応

1.3.70以降のKotlin/NativeはSIMD型に対応しています。 これによって、人気のApple製フレームワーク(AccelerateSpriteKit)など、より多くのサードパーティAPIをKotlin/Nativeから使用できるようになりました。

スクリプト作成

バージョン1.3.70ではIntelliJ IDEAとKotlinのコマンドラインツールでKotlinスクリプトをより使いやすくするため、複数の改善が行われています。
また、Kotlinスクリプトの作成をよく理解できるよう、サンプル付きのプロジェクトを用意しています。 このサンプルには標準スクリプト(*.main.kts)の例や、スクリプトAPIの使用例とカスタムスクリプト定義の例が収録されています。 ぜひお試しいただき、課題トラッカーでご意見をお寄せください。

コンパイラとIDEでの kotlin-main-kts 対応

Kotlin 1.3では、基本的なユーティリティスクリプトの作成と使用を単純化する kotlin-main-kts アーティファクト を導入しました。 このアーティファクトはKotlinコンパイラとIntelliJプラグインによりデフォルトで読み込まれ、*.main.kts スクリプトが初期状態でサポートされるようになりました。 具体的に言えば、kotlin-main-kts.jar をクラスパスに追加することなくこのようなスクリプトを使用できるようになりました。
これによって、IntelliJ IDEAがソースディレクトリの外でも *.main.kts ファイルのハイライトと移動に対応しました(動的依存関係の解決も含む)。
また、コンパイル済み *.main.kts スクリプトをキャッシュして後続の実行処理を大幅に高速化することで、実行パフォーマンスを改善しました。

コマンドラインツール

また、コマンドラインツールでのKotlinスクリプト作成対応を強化しました。
Kotlinコマンドラインコンパイラと共に配布される kotlin ランナーがスクリプトの実行に対応しました。 kotlin でスクリプトを実行するには、次のようにスクリプトファイル名を渡します。

このように呼び出すと、コンパイラを -script オプションで呼び出した場合とまったく同じようにスクリプトが実行されます。 kotlin は初期状態で .main.kts スクリプトを認識します。
kotlin ランナーも式の評価に使用できます。 式を評価するには、次のように –e/-expression オプションの値として式を渡します。

結果はすぐに取得できます。
Kotlinコマンドラインコンパイラにも同じ機能が追加されていますが、オプション名が -Xexpression と異なっています。

アップデート方法

いつものように、play.kotl.inKotlinをオンラインで試すことができます。

  • GradleとMavenの場合:コンパイラと標準ライブラリのバージョンに1.3.70を使用します。 GradleMavenのドキュメントをご覧ください。
  • IntelliJ IDEAAndroid Studioの場合:Kotlinプラグインをバージョン1.3.70にアップデートします。 Tools | Kotlin | Configure Kotlin Plugin Updates を使用して「Check again」ボタンをクリックします。
  • Eclipseの場合Marketplaceを使用してプラグインをインストールします。
  • コマンドラインコンパイラは、Githubリリースページからダウンロードできます。

この新リリースで問題が発生した場合は、Slackのフォーラムこちらで招待を受けてください)で支援を依頼するか、課題トラッカーで課題を報告してください。

Let’s Kotlin!

外部貢献者

コレクション用のビルダー関数対応を行ったFleshgrinder氏と、reduceOrNull()関数を追加したadellibovi氏に感謝いたします。

また、このリリースに含まれていたプルリクエストの所有者であるすべての外部貢献者にも感謝いたします。

[原文Original post in English is written by Pavel Semyonov

image description