Используем Kotlin для кровавого enterprise в проекте, где 95% кода на Java и 5% Kotlin.
Перечислю самые проблемные для нас вещи:
• Стек ошибок довольно часто ведёт «в никуда», то есть в отличии от родного java-стека, понять место ошибки из стека не представляется возможным
• Default methods
https://youtrack.jetbrains.com/issue/KT-4779• Нет встроенных параллельных вычислений a-la Stream. Переходы от Sequence к Stream и обратно хотя и стали лучше в последних версиях, но всё-таки не так просты
• Куцая рефлексия с постоянной конвертацией в java и обратно. Рефлексия в java прямо скажем не айс, так что непонятно почему бы её не скрыть за красивым фасадом
Кроме того, есть вещи, которых ожидаешь от свежего языка, но которых не обнаруживаешь:
• Generic function references
https://youtrack.jetbrains.com/issue/KT-12140• Нет поддержки на уровне языка отделения mutable классов от immutable, mutator/accessor методов, … что приводит к тем же проблемам в дизайне дженериков, что и у Java. Про выведение иммутабельности я уж молчу
• Вообще работа с дженериками осталась такая же убогая, как в Java. Почему бы хотя не давать сослаться на себя же? Попробуйте на Kotlin честно написать функцию clone, интерфейс SelfComparable, дженерик билдер или какой-то монадический интерфейс и вы получите всё тот же ”адъский java говнокод”, где у всякого дженерика не меньше десятка параметров, хотя все они выводятся из одного
• Нет immutable коллекций, plus для коллекций делаются через копирование
• Нет коллекций в стиле guava c ленивыми вычислениями (да, можно использовать guava + куча extensions)
• Нет полноценной поддержки copy-on-write, есть только какие-то огрызки у data class вроде copy. Да это приятно, но не чувствуется цельности
• Паттерн матчинг не знает про рефлексию. Если делать when для значения Class или KClass, например через isAssignableFrom, придётся всё равно приводить значение явно
• Reified только в inline, а inline не доступен для локальных функций. Это бывает довольно печально
• Также как JDK нет никакой поддержки иерархичных данных (TreeNode)
• Нет встроенной мемоизации для функциональных типов. Есть встроенный неплохой Lazy, и на том спасибо.
• Кроме extension методов не хватает возможности заимплементить чужому классу свой интерфейс. Конечно же только как сахар в compile time (вместо вызова extension адаптер-метода asOtherType()).
Возможно, часть проблем уже решена, а мы не знаем?