Functional Programming
Kotlin
Comments 10
+4

Преимущества предлагаемого решения так и не понял. Классический вариант с try/catch примерно одинаково выглядит и работает во всех императивных языках, от C++/Java/C# до PHP/JS/Ruby, поэтому большинству будет понятен интуитивно. Здесь же появляются — Try, monad, binding, pure, recover, recoverWith, flatMap, bind, и в другом языке\другой библиотеке они будут называться по-другому.


Еще одна проблема — иллюзия безопасности. Когда вы где-то обрабатываете ошибки явно создается впечатление, что в остальных строках ошибка впринципе не может возникнуть, однако язык/рантайм таких гарантий не дает. В итоге, если у вас есть какие-то требования к стабильности, то вам все равно придется на некотором уровне обернуть весь код в try/catch — чтобы, например, при непредвиденной ошибке при обработке одного запроса упал только этот запрос, а не весь сервис.

+3
Честно говоря, совершенно не убедительно. Профита не видно. Какой смысл оборачивать в Try всё подряд, если тоже самое делает обычный try-catch и поддержка nullability, типа
fun makeRequest(request: String): List<Any>? = try {
    listOf()
} catch (e: Exception) {
    null
}

fun main(args: Array<String>) {
    makeRequest("body")?.let { 
        it.map { it.toString() } 
    } ?: emptyList()
}

тоже самое, только из коробки, без доп-оберток и матчинг эксепшена по типу
-1
тоже самое, только из коробки

Нет, не тоже самое. Вы просто проглотили исключение. В Try же exception есть и в конце статьи написано как оно может быть обработано.
Профита не видно

В статье не самым лучшим образом отражено, а вообще это нужно для того, чтобы можно было делать цепочку из монад с дальнейшей обработкой.
-1
Спасибо за комментарий!
Наверное, главная цель статьи — это, чтобы на хабре Arrow хотя бы упоминался (не нашел по нему статей). А чтобы это упоминание не отпугивало обилием информации (а библиотека ведь очень богатая) — статья должна была быть поверхностной. Поэтому абзац про цепочки монад был написан — и вырезан перед отправкой.
0
Нет, не тоже самое. Вы просто проглотили исключение. В Try же exception есть и в конце статьи написано как оно может быть обработано.
ну да, если его надо обработать выше, надо просто этот же код написать выше, в чем тут проблема-то? и `try` надо только в одном месте написать.
цепочку из монад с дальнейшей обработкой

вызов метдов с `try-catch` это разве не цепочка с обработкой? в чем профит-то?
Усложнение всё-таки должно быть чем-то оправдано, того, что я увидел в статье явно не хватает, чтобы взять это в использование в каких-то реальных кейзах, которые я использую. Я использую цепочки обработки для коллекций, например, там понятно, что мы получаем, декларативность, скрываем не относящийся к происходящему и повторяющийся код, а тут что? Заменили один механизм из коробки на другой из библиотеки, при этом декларативности особенной или переиспользования или понятности не получили, только усложнение и дополнительные зависимости.
+1
вызов метдов с `try-catch` это разве не цепочка с обработкой? в чем профит-то?

Ну принцип тот же, что и в Stream API — это практически цепочка монад. Удобно будет например внутрь map или filter засовывать обработку try-catch?
0
если для каждого элемента важно значение или исключение, то это может быть удобно, да, как например это сделано в CompletableFuture. Но там это немного более уместно, потому что предполагает выполнение какого-то кода, который может свалиться. В концепции мэпа больше предполагается, что этот код будет падать только если совсем. Если код для каждого элемента может падать, то чаще для этих методов будет полезнее что-то вроде:
inline fun <R> tryOrNull(block: () -> R?): R? = try {
    block()
} catch (e: Exception) {
    null
}

fun aaa() {
    listOf(1, 2, 3).mapNotNull { tryOrNull { it / 0 } }
}
+6
По моему это очень смешно.
Сначала придумывают checked exceptions в Java.
Для того, чтобы
любой кто будет читать этот код после тебя (а такие скорее всего будут) уже по сигнатуре сможет понять, что исполнение кода может привести к ошибке — и написать код её обработки. Тем более, что компайлер заругается, если это не будет сделано.


Потом говорят — не, не хотим возиться и всюду загрязнять сигнатуры методов, и перестают их использовать и вообще не делают такое в Котлине и Скале.

Потом говорят — как же так? Мы же не знаем какой может тут вылететь эксепшн!
Давайте сделаем Try в Котлине и скале, чтобы
любой кто будет читать этот код после тебя (а такие скорее всего будут) уже по сигнатуре сможет понять, что исполнение кода может привести к ошибке — и написать код её обработки. Тем более, что компайлер заругается, если это не будет сделано.
UFO landed and left these words here
0
При дизайне языка С# было принято решение отказаться от checked exceptions. Андреас Хейлсберг (дизайнер языка) объяснил это тем, что преимущества от checked exceptions полностью невелируюся их недостатками. Обычно исключениям (обычным) ставят в вину, что их можно и не обрабатывать (в отличие от), но при этом не говорится, что часто их и не нужно обрабатывать, по крайней мере, не во всех слоях программы, в то время как любая принудительная обработка ошибок (как, например, в статье) приводит к бессмысленному коду, просто чтобы перекинуть исключение выше. Для функционального подхода это еще можно понять, но в ООП это просто замена одного геморроя другим.
Only those users with full accounts are able to leave comments.  , please.