>В Java ты чаще понимаешь по узкому контексту, что происходит. a = b — запись в поле или локал, a[1] = 2 — запись в массив. В Котлине за любым простым выражением может стоять сколь угодно сложный код из-за всяких умностей вроде перегрузки. Без IDE ничего не поймёшь. А IDE плохо, когда ты едешь в поезде и видишь, что свинговый жабоинтерфейс высасывает из ноутбука батарейку как вампир.
Относительно Java - да, мы теряем однозначность, но получаем лаконичность. Ввиду того, что в среднем случае все пишут в IDE (а также JB пропагандирует это), то решение логичное.
Относильно JVM-мира - стоит отметить, что набор возможных перегрузок строго ограничен, что позволяет меньше офигевать от абсолютной кастомности и неявности происходящего (привет Dynamic, implicit и ещё миллиарду фич из Scala!). Также весь набор неявностей хорошо поддерживается в IDE (и снова привет implicit)
>Котлин даёт одинаковый API для коллекций и сиквенсов, из-за чего люди злоупотребляют цепочками map/filter на коллекциях, создавая кучу промежуточных неленивых копий. Стримы в джаве специально введены для различия между ленивой и неленивой коллекцией. Да, есть инспекция в IDE для этого — потому что инспекции призваны исправлять недостатки языков.
Сравнение некорректно, т.к. в джаве для коллекций этих операций просто нету, что выглядит в среднем случае ужасно, т.к. набор из 1-2 операций ты вынужден делать либо на стримах, либо на циклах, что просто дико захламляет код:
list.stream().filter(i -> i > 5).collect(Collectors.toList())
vs
list.filter { it > 5 }
Насчёт проблемы самой по себе - она есть, но незначительна. Причин несколько:
1. Мы работаем в IDE.
2. Цепочку вызовов и глазами на ревью хорошо видно.
3. Консистентность апи очень помогает из-за того, что надо меньше думать о названиях.
>Кстати, об IDE. Насколько хороша поддержка Kotlin в IntelliJ IDEA? Она действительно лучше, чем для Java? Есть большие сомнения. Может быть, кому-то из JB хватит духу проадвокатировать по данному вопросу.
Примечание - я не из JB. На мой взгляд в среднем случае не уступает. Иногда мне может не хватать постфиксных шаблонов, но я их дописываю сам.
>Котлин форсит использование it, что приводит к нечитаемому коду. Что-нибудь типа
seq.map { it -> foo(it, 1); }.map { it -> bar(it, 2); }.filter { it -> it.getBaz() > 0; }. Что это вообще было? Имена переменным даны не зря! А тут получается монолог вроде «Возьмём это, прикрутим к нему то, потом его закрутим и если оно стало больше того, то наденем сверху шарнир».
В целом - Немного непонятно, зачем it объявлен явно, а также поставлены точки с запятыми.
Относительно Java - мы получили дополнительную возможность, которую удобно юзать в коротких лямбдах (коими являются лямбды в твоём примере). Если будет становиться неочевидно - просто объявляешь параметр лямбды явно.
Относительно JVM-мира - в Груви тоже самое (оттуда и взяли), в Scala вообще '_', который победитель по возможной неочевидности.
>Цепочки вроде ?.let { foo(it); }?.let { bar(it); } — это вообще ад и должны быть запрещены в декларации о правах человека. И это считается идиоматично, Карл. В отличие от нормального if. Читать такой код невозможно.
Как упомянули уже в чате, с ссылками на методы ситуация резко меняется:
?.let(::foo)?.let(::bar)
Также стоит отметить, что никто не мешает использовать if, вывод типов внутри будет работать.
Ну и в среднем случае нету нужды в цепочках let (больше одного вижу почти никогда)
>От интеропа с джавой кровь идёт из глаз. А тут всякие JvmStatic и JvmName, и код превращается в цирк с конями.
Относильно Java:
Проблема есть и это логично, что она возникла, т.к. языки не совпадают.
Решения простые:
1. Забить на идеальный интероп
2. Проставлять
3. Возвращаться на джаву, если проставлять приходится слишком много
Проблема не такая большая (всё аннотировать не нужно, только стыки апи), как мне кажется.
Относительно JVM-мира: Ну, либо мы имеем те же аннотации (привет
@throws(classOf[IOException]) из Scala), либо не имеем функционала, чтобы эти проблемы возникли. Ну или не имеем интеропа.