Сьогодні в меню — новий Kotlin 2.0
Всім привіт! З вами знову Бодька. Можете пригадати мене за циклом статей про Kotlin Multiplatform. Давно я тут не був, і багато чого за цей час сталось, як-от реліз Kotlin 2.0, довгоочікуваного K2, вибух екосистеми Kotlin Multiplatform новими бібліотеками Jetpack, а також розв’язання багатьох накипілих проблем із Compose, особливо Compose for Web.
Ну, і заспойлерили деякі майбутні фічі мови Kotlin. Ух, у мене аж апетит до мультиплатформи знову прокинувся.
Аперитив — майбутні фічі
Почнімо з тих самих фічей. Нам їх, як у мемі про рибов, тільки показують. Вони поки що в розробці, і з’являться у Kotlin 2.1 або 2.2.
dataarg-класи
У вас часто буває, що доводиться механічно копіпастити певний набір аргументів, оскільки вони потрібні кожній функції або конструктору? Тепер для цієї проблеми є розв’язання. Наприклад, у вас у Compose-коді є низка кнопок різного стилю, і всі ж потрібні! Тому можна написати dataarg-клас вигляду:
dataarg class ButtonArgs(
modifier: Modifier = Modifier,
onClick: () -> Unit = { },
contents: @Composable () -> Unit
)
...і використати ось так:
@Composable
fun MaterialOneButton(args: ButtonArgs) {
/* ... */
}
@Composable
fun MetroButton(args: ButtonArgs) {
/* ... */
}
@Composable
fun iOSButton(args: ButtonArgs) {
/* ... */
}
...і цей код працюватиме так само як і функції зі звичайними повторюваними сигнатурами:
fun MaterialOneButton( modifier: Modifier = Modifier, onClick: () -> Unit = { }, contents: @Composable () -> Unit ) { /* ... */ } @Composable fun MetroButton( modifier: Modifier = Modifier, onClick: () -> Unit = { }, contents: @Composable () -> Unit ) { /* ... */ } @Composable fun iOSButton( modifier: Modifier = Modifier, onClick: () -> Unit = { }, contents: @Composable () -> Unit ) { /* ... */ }
...і якщо доведеться масово міняти сигнатури, то достатньо просто змінити те, що є у dataarg-класу. З’явиться... Невідомо, коли.
Guards (ґарди)
Напевно, вам всім відома ситуація, коли є довгий when statement
:
val status: Status = ... val doRickroll = true when { status == Status.OK -> "Okay, move on." status == Status.BadRequest -> "Open me! https://www.flickr.com/photos/girliemac/6540669737/in/album-72157628409467125/" status == Status.Teapot && doRickroll -> "Open me! https://youtu.be/dQw4w9WgXcQ" else -> "I'm a teapot" }
...і ви бажаєте його скоротити через when with subject
:
when (status) { Status.OK -> "Okay, move on." Status.BadRequest -> "Open me! https://www.flickr.com/photos/girliemac/6540669737/in/album-72157628409467125/" Status.Teapot && doRickroll -> "Open me! https://youtu.be/dQw4w9WgXcQ" else -> "I'm a teapot" }
...і стрічка коду з рікроллом підкреслена червоним. Механізм ґардів дозволяє обійти це обмеження і зарікроллити нашого юзера:
Status.Teapot if (doRickroll) -> "Open me! https://youtu.be/dQw4w9WgXcQ"
Never gonna give you up, never gonna let you down... Ой. З’явиться у Kotlin 2.1 як бета-фіча, а зараз доступна як експериментальна.
Context receivers parameters
Маєте такий код:
withAutoClose { val lyrics = open(File("Never gonna give you up - Lyrics.txt")) } interface AutoCloseScope fun withAutoClose(block: AutoCloseScope.() -> Unit) fun AutoCloseScope.open(file: File): InputStream
...але навіть завзятим користувачам Python не подобається вкладеність функцій. А що, як спробувати це:
withAutoClose { val lyrics = File("Never gonna give you up - Lyrics.txt").open() }
Виглядає неймовірно, але щоб зробити цей код валідним, треба більше контексту. AutoCloseScope.open()
уже має ресивер, тому нам потрібно вказати додатковий контекст у withAutoClose()
:
fun withAutoClose(block: context(_: AutoCloseScope).() -> Unit)
...та скористатись ним:
context(scope: AutoCloseScope) fun File.open(): InputStream
Все, тепер ця функція виглядає красиво, ідіоматично та приязно до аналізу IDE. Вже доступна як експериментальна фіча, буде в беті у Kotlin 2.2
І хоч би за всім цим цукром хоч трохи мови залишилось, кхм...
Основна страва — надшвидкий K2
У самому K2 нічого, крім оптимізації, особливого для більшості програмістів нема. Є багато змін для тих, хто пише плагіни компілятора та IDE, але про них я тут не розповім. У JetBrains кажуть, що вони скоротили час компіляції Kotlin-коду навпіл (отже, ніякої кави під час ./gradlew build clean
) та зробили фронтенд K2 більш «платформно-агностичним», тобто менш залежним від усіх платформ.
Заміряти на своєму комп’ютері та перевірити їхню інформацію достеменно я не зміг, інакше написання цієї статті зайняло б кілька тижнів. Але я помітив відчутну різницю у швидкості компіляції «чистих» та «релізних» збірок та меншу, але все одно помітну при інкрементальній компіляції (вона найчастіше трапляється, коли ви трішки змінили код і хочете перезапустити програму, щоб побачити зміни наживо).
А, ще дещо. Іще рік тому в Android Studio та IntelliJ IDEA з’явився режим K2 — під час його використання для аналізу та індексації проєктів використовується той самий фронтенд, що і для компіляції. Той самий K2, що майже унеможливлює false positives та прискорює індексацію... в теорії.
Бо на практиці режим K2 нестабільний. У мене його не вдалось завести навіть на базових шаблонах з IntelliJ. До речі, особливо смішно те, що в Android Studio у режимі K2 не працює... розпіарений плагін Gemini, який Google так любить і обожнює.
Друга страва — екосистема Kotlin Multiplatform
Єдине, що із ним сталось — так це вибух у площині first-party-бібліотек. Kandy (візуалізація даних) та Dataframe (перемелення даних) дають широкі можливості для дата-саєнтистів — тих самих, що відкрили ящик Пандори та запустили хайп довкола генеративного ШІ.
Стандартна бібліотека, Coroutines, IO, Serialization — усе те саме, чим вони були раніше, але більше, краще, швидше, вище, сильніше. Покращена документація, більше common-типів, покращена сумісність з кількома платформами одночасно. Вийшов із бети й Kover — CodeCov, але вибудований із задатком у Kotlin Multiplatform. Оновили гайдлайни написання API.
Десерт — солоденький Compose (обережно, десерт ду-у-уже жирний)
Але що Google обожнює точно більше за ШІ, так це Compose. Бо там нарешті придумали розв’язання проблеми плутанини із Compose Compatibility Map. Інструкція проста, як п’ять центів. Зберігайте. А тепер готуйтесь:
- Compose for iOS — вийшов з альфи. Тепер він у Beta. Не буде таких штурмів під час міграції на нові версії;
- Jetpack Navigation, Lifecycle View Models, ресурси — тепер частина Compose Multiplatform на всіх платформах (нарешті!);
- Compose for Web — більше не експериментальний. Тепер він у стадії альфа. Більшість core API реалізовано. Працює на Kotlin/Wasm.
Попереджав — буде жирно.
Бонусний смаколик — новий маскот!
Представили нового маскота. На відміну від попереднього, він має ім’я — Коуді (Kodee). Ви тільки подивіться на цю милоту!
А що це було?
Це був Бодя. Він розказав вам, що приніс із собою реліз Kotlin 2.0, а саме — про багато чудових змін в екосистемі, потужну оптимізацію, поступовий вихід з експериментального стану багатьох чудових проєктів та багато чого іншого. Повторімо?
- K2 прискорив збірку проєктів «з нуля» удвічі.
- Пообіцяли швидше робити нові фічі для мови.
- Можна помацати Guards та Context parameters, анонсували класи
dataarg
. - З’явився тулкіт для дата-саєнтистів. Тепер графіки можна робити на Kotlin завдяки Kandy та Dataframe.
- Тепер відсоток покриття коду тестами можна рахувати і в мультиплатформі завдяки Kover.
- Google взялись за голову та послали якомога далі той триклятий Compatibility Map.
- Compose Multiplatform стабілізується та процвітає.
- І найважливіше, найбільш тектонічна зміна в екосистемі Kotlin, що грозиться влаштувати людству апокаліпсис болючіший, ніж той, що застали динозаври — новий маскот.
Смачного, не обпечіться. Зміни дуже гарячі! Розкажіть, що смакує вам найбільше. Бувайте!
4 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів