Kotlin 1.7.0-Beta Released
一言で表すと
概要
Changes to builder inference
今までは -Xenable-builder-inference コンパイラオプションをつけないとビルダー推論が有効にならなかったが、1.7ではこれをつけなくても通常の型推論で型に関する十分な情報を取得できない場合に自動でビルダー推論がアクティブになる
mayamito.icon 具体的な例が知りたい🤔
chigichan24.icon 以前は @BuilderInferfence かなにかを付ける必要があったやつかな
標準APIであるものだと buildList() buildMap() あたり
code:kotlin
val x = listOf('b', 'c')
val y = buildList() {
add('a')
addAll(x)
add('d')
}
code:kotlin
val x = mapOf('b' to 2, 'c' to 3)
val y = buildMap<Char, Int>(x.size + 2) {
put('a', 1)
put('c', 0)
putAll(x)
put('d', 4)
}
println(y) // {a=1, c=3, b=2, d=4}
The return of the min() and max() collection functions
もともと min() max() はnullableな値を返す関数だった
1.4でコレクション型に minOrNull() maxOrNull() を導入し、古い min() max() はDeprecatedになった
1.7では min() max() をnon-nullな値を返すか例外を投げる関数として再び導入する
code:kotlin
val numbers = listOf<Int>()
println(numbers.maxOrNull()) // "null"
println(numbers.max()) // "Exception in… Collection is empty."
Stabilizing of definitely non-nullable types
ジェネリスクのときに T & Any という表記にすることで絶対にnullでない型を区別することができる
code:kotlin
fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y
fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y
fun main() {
elvisLike<String>("", "").length // OK
elvisLike<String>("", null).length // Error: 'null' cannot be a value of a non-null type
elvisLike<String?>(null, "").length // OK
elvisLike<String?>(null, null).length // Error: 'null' cannot be a value of a non-null type
}
1.6.20から導入、1.7.0からデフォルトで有効になっているよ
ほとんどの場合、Kotlinのジェネリクスはうまく動く
code:kotlin
fun <T : CharSequence?> foo(t: T, tn: T?) {
t.length // nullの可能性があるため呼べない
tn.length // nullの可能性があるため呼べない
}
fun <F : CharSequence> bar(f: F, fn: F?) {
f.length // ★ nullの可能性はないため呼べる
fn.length // nullの可能性があるため呼べない
}
あるJavaのintefaceをKotlinで実装する際に問題が発生した
code:java
public interface JBox<T> {
<T> void put(@NotNull T t);
}
Tをnull許容型にし、tをnon nullにすることができない
T & Any で絶対にnull許容型ではない型を定義できるようにする
code:kotlin
interface JBox2<T> : JBox<T> {
override fun put(t: T & Any)
}
構文の注意事項
is や as のそばでは使えない
expr as T & Any は (expr as T) & Any か expr as (T & Any) かわからない
fun T & Any.foo() は fun (T & Any).foo() である必要がある
T & Any.() -> Unit は (T & Any).() -> Unit である必要がある
Mori Atsushi.icon Any が赤だったり青だったりするのはなぜw
結構賛否がありそう
初期の案では!!が使われていた
code:kotlin
interface B<T1> : A<T1> {
override fun foo(x: T1?): T1?
override fun bar(x: T1!!): T1!!
}
Mori Atsushi.icon 少なくともこれよりは良さそう
Mori Atsushi.icon 今後一般的な交差型(T & U等)が使えるかについては特に議論がなさそう
Matching with Regex at a particular position
matchesAt 指定した位置で正規表現に当てはまればtrue、それ以外はfalseを返す
code:kotlin
fun main(){
val releaseText = "Kotlin 1.7.0 is on its way!"
// regular expression: one digit, dot, one digit, dot, one or more digits
val versionRegex = "\\d.\\d.\\d+".toRegex() println(versionRegex.matchesAt(releaseText, 0)) // "false"
println(versionRegex.matchesAt(releaseText, 7)) // "true"
}
matchAt 指定した位置で正規表現に当てはまれば一致した内容を、それ以外はnullを返す
code:kotlin
fun main(){
val releaseText = "Kotlin 1.7.0 is on its way!"
val versionRegex = "\\d.\\d.\\d+".toRegex() println(versionRegex.matchAt(releaseText, 0)) // "null"
println(versionRegex.matchAt(releaseText, 7)?.value) // "1.7.0"
}
もともとJVMにはあったみたい
JSやNativeにも対応
New Kotlin/Native Memory Manager
引き続きフィードバックをもらいながら開発中らしい。
JVMとNativeの差分をなるべく埋めるように作っている。
プラットフォームごとに一貫したエコシステムは大事。
こういう差分をなくすことで、Android / iOS とかのcross platformなアプリケーションを開発する際に便利になるよ。
Thread間のオブジェクトの共有に対して制限を設けない(?)
(The new Kotlin/Native memory manager lifts restrictions on object-sharing between threads.)
メモリーリークしない!特別な管理や、アノテーションもいらない!それでいて簡単に並行プログラミングできる
新しいマネージャについてはここで詳細を書いてるよ。
去年の8月の記事。すでに見た。
マイグレーションの方法はここに書いている。
code: gradle
// build.gradle.kts
kotlin.targets.withType(KotlinNativeTarget::class.java) {
binaries.all {
}
}
基本は、こんな感じに設定するだけ
まだ、基礎的な部分しか作ってないからパフォーマンスに問題がある。
Mori Atsushi.icon 😇
よくわかってないが、Kotlin から Swift の コールバックの呼び出し(またはその逆) などのケースで特に厳しいらしい。
一時オブジェクトをヒープに長いこと保持する -> GC のパフォーマンスが落ちる
autoreleasepool をつけると改善するなどと書いている。
コンパイラのキャッシュがないので、デバッグバイナリのコンパイルが低速
Mori Atsushi.icon 😇
iOSなどで、プロセスがBGにいっても、特にGCのコレクターがスロットルダウンしない。
WASM(などのpthreadを持たないやつら)が動かない。
Support for named capturing groups in JS and Native
正規表現の名前付きキャプチャグループ(named capturing groups ) が JS や Native でも動くようになった。
構文は以下
(?<name>group)
EcmaScript とかと一緒
取り出すときは groupsで参照すればよろしいっぽい。
code:kotlin
fun main() {
val regex = "\\b(?<city>A-Za-z\\s+),\\s(?<state>A-Z{2}):\\s(?<areaCode>0-9{3})\\b".toRegex() val input = "Coordinates: Austin, TX: 123"
val match = regex.find(input)!!
println(match.groups"city"?.value) // "Austin" — by name println(match.groups2?.value) // "TX" — by number }
backreferencing もできるよ。
//k <name> で取れるらしい。
code:kotlin
fun backRef() {
val regex = "(?<title>\\w+), yes \\k<title>".toRegex()
val match = regex.find("Do you copy? Sir, yes Sir!")!!
println(match.value) // "Sir, yes Sir"
println(match.groups"title"?.value) // "Sir" }
気になるポイント
メモ
コメント