169 похожих чатов

Привет! Есть вопросик к коммьюнити: Кто-нибудь хотел бы иметь в котлине что-то

вроде scala-вских for-comprehensions?
Если да, то поголосуйте за тикет про это, пожалуйста.

(знаю, что в чатике есть мощные функциональщики, но сейчас интересует исключительно прагматическая сторона и применение в проде, без упоминая слова монады вообще c: )

Просто известно, что скалисты пользуются ими и в хвост, и гриву, в моем окружении тоже много кто хочет такое, но официально к тикету про это никакого интереса проявлено не было.

P.S. Для тех, кто не слышал про такое, супер-краткий обзор: функциональное программирование на котлине это круто, но часто оказывается, что читать вложенные преобразования данных функциями вида map и flatMap довольно тяжело, а ля callback hell.

Ну, совсем тупой пример еще даже на Java:

results.stream().flatMap(
res -> f(res).flatMap(
res1 -> res1.flatMap(
res2 -> res2.map( /* and so on */ ))));

И вот говоря очень кратко, for-comprehensions это простой синтаксический сахар для такого. Он применим для любых сущностей у которых есть методы вида map, flatMap и filter, например, Optional, List, Future, Flowable, Observable, Spring Stream's Flux и т.д, т.е. у дофигищи повседневных вещей.

И вот если в котлине будут for-comprehensions, то код вида

fun login(oldAuth: AuthToken): SomeContainer<UserModel>> {
credentialService.oauthLogin(oldAuth).flatMap { token ->
securityService.getRole(token).flatMap { role ->
credentialService.getUserDetails(token, role).map { userDetails ->
(token, role, userDetails)
}
}
}
.filter { (token, role, userDetails) -> areValidModelParams(token, role, userDetails) }
.flatMap { (token, role, userDetails) -> computeUserModel(token, role, userDetails) }
...

будет примерно выглядеть как

fun login(oldAuth: AuthToken): SomeContainer<UserModel> =
for {
token <- credentialService.oauthLogin(oldAuth)
role <- securityService.getRole(token)
userDetails <- credentialService.getUserDetails(token, role)
if areValidModelParams(token, role, userDetails)
userModel <- computeUserModel(token, role, userDetails)
}
yield userModel

10 ответов

54 просмотра

По-моему это ужасно. Вообще не понятно, что оно делает. Не говоря о том, что пример плохой, если у вас там там что-то типа Optional, то в котлин оно вообще не нужно из-за нулябельности.

Ну для nullable типов, Result, а также Option, Either и Eval из Arrow есть собственно блоки в самом Arrow: https://github.com/arrow-kt/arrow/tree/main/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations (Формально для nullable есть и просто ?. но да, такие блоки помощнее) Для листов иногда хочется в задачах для условного Advent of Code (кстати начался, да), в реальных задачах как-то не сложилось с нуждой лично у меня 🤷‍♀️ Всякие промисоподобные вещи не особо казалось удобным (но тут можно поспорить, да), у реактивщины вроде нету никакого одного flatMap, чтобы так делать Короче какие-то обходные пути и сейчас есть (раньше в Arrow и для листов вроде был, так что наверное и это можно вернуть). Может что-то для упрощения работы с тем же Result/Either было бы приятно иметь из коробки, но непонятно как лучше, как в условном хаскеле/скале или как-то иначе

Посмотрите, как сделано в Arrow: https://arrow-kt.io/docs/0.10/patterns/monad_comprehensions/. Вот пример кода val university: IO<University> = IO.fx { val (student) = getStudentFromDatabase("Bob Roxx") val (university) = getUniversityFromDatabase(student.universityId) val (dean) = getDeanFromDatabase(university.deanId) dean } честно говоря, не вижу причины, зачем ду-нотацию тащить в язык, если её можно реализовать на уровне библиотеки с помощью корутин.

Alexander-Bashkirov Автор вопроса
Ilmir
Посмотрите, как сделано в Arrow: https://arrow-kt....

Кстати, а насколько оно эффективно в байт-коде? Там от рантайма корутин ничего не остаётся, или оно наоборот на него завязано?

Alexander Bashkirov
Кстати, а насколько оно эффективно в байт-коде? Та...

Оно не зависит от kotlinx.coroutines. Единственное, что от корутин требуется - это продолжения. А они оптимизированы донельзя. Плюс на всю цепочку аллоцируется только одно продолжение, а не по лямбде на каждый шаг, если делать через дешугаринг.

Alexander-Bashkirov Автор вопроса
Ilmir
Оно не зависит от kotlinx.coroutines. Единственное...

Любопытно, спасибо! Вот, ещё один козырь в крышку гроба ду-нотации а котлине.

Ilmir
Оно не зависит от kotlinx.coroutines. Единственное...

А разве там не было истории о том, что эрроу использует корутины не так, как вы предполагали, потому вы не можете обещать, что вы их не сломаете? :)

Andrew Mikhaylov
А разве там не было истории о том, что эрроу испол...

Намерено ломать эрроу мы не планируем. И сейчас если ломать корутины, то это будет несовместимое изменение. А на это нужны ооочень веские причины. Так что, вероятность, что мы сломаем эрроу - минимальная.

Кажется надо проголосовать, чтобы это не приняли 😂

Похожие вопросы

Обсуждают сегодня

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Карта сайта