Обновить

Комментарии 64

Как вы на практике с ним работаете-то, в ситуации когда идея недоступна для скачки. Обычным маленьким компаниям условно «можно» скачать, подхимичить, но вы банк… Джетбрейнз прямым текстом говорит мы в России ничего не будем разрешать, даже бесплатный продукт, нам санкции всего мира запрещают (а вот микрософту что-то н чего не запрещает…).

Ставите openide что ли? В vs code работать пока с котлином невозможно, уровень плагина не тот.

Я GigaIDE использую. Можно взять OpenIDE. Обе среды поддерживают Kotlin

Хорошо, а приятно пользоваться языком, чьи авторы на багрепорты от русских отвечают в стиле «вы из России, мы вас не обслуживаем»?

Посмотрел: я 72 issue создал в их YouTrack - ни на один так не ответили. Что я делаю не так?

Ну а людям именно так отвечают:

https://youtrack.jetbrains.com/issue/WEB-59910/Instantiation-Expressions-doesnt-work-with-comma#focus=Comments-27-6966043.0-0

По их отписке стандартной можно погуглить и увидеть, что они многим так отвечают

По слову sanctions в youtrack около 500 проблем таким образом закрытых находится. То что у вас не закрыли это скорее их недосмотр, а не то что этого нет.

Вот еще эпичный диалог, как раз про котлин:

https://youtrack.jetbrains.com/issue/KT-56783/kotlinc-js-empty-output-IR

Jetbrains просто соблюдает законодательство своей юрисдикции и на это указывают. Претензии должны быть не к ним.

Ну простите меня, но это бред. Как же работают тогда компании которые эти юрисдикции нарушают?

Как по мне, так jetbains не просто соблюдают законодательство, а даже стараются сделать намного больше чем от них требуют

Ну простите меня, но это бред. Как же работают тогда компании которые эти юрисдикции нарушают?

Приведите, пожалуйста, пример компании, которая нарушает законы своей юрисдикции.

Так же как и с Java. GigaIDE, openIDE, community edition.

Community edition точно так же лицензия их запрещает использовать в России. Остаются только пересборки наши.

Майкрософту не мешает?

The company suspended all new sales of Microsoft products and services in Russia (but continue existing access) and it is stopping many aspects of the business in Russia in compliance with governmental sanctions decisions. Microsoft restricted Windows 11 update for Russians but later Microsoft returned the ability to download and install Windows 10, 11, Windows 8.1. and Windows 7 for Russians, however customers in the country are still unable to download and install the company’s latest operating system. The US Treasury has reached an agreement with Microsoft to settle the dispute over the IT giant's violation of sanctions against Cuba, Iran, Syria and Russia: the company will pay almost $3 million and $1.3 thousand each. clauses are violated, according to the statement of the US Ministry of Finance. Microsoft has stopped warranty service for Xbox consoles in Russia. Russian companies will soon not be able to use official Microsoft products. Since October 1, 2023 the corporation no longer extends licenses for its software. Microsoft has again opened access to Windows and Office updates for Russians without using a VPN. You can install them in two ways: from the company's official website or through the appropriate menu of the OS/software package. Significantly reduced revenue in 2023 vs 2022. Microsoft started to cut off russian companies from cloud services. Microsoft continues to reduce its presence in Russia, closing 13 branches and divisions in December 2024 and January 2025. The main legal entity of Microsoft Corporation, Microsoft Rus LLC, intends to file for bankruptcy, according to Fedresurs data. To do this, the company will apply to the Moscow Arbitration Court.

А как же sealed и корутины как минимум?

Согласен, это тоже можно было бы добавить, но я хотел прежде всего сравнивать с аналогами в java.

Получается, можно было бы сравнить с виртуальными потоками, если не ошибаюсь

Автор же сразу оговорился, что не добавлял то, что есть в Java. В Java уже есть как sealed интерфейсы, так и Project Loom, полностью заменяющий корутины (понятно, что какой-нибудь андроид сидит на старых jdk, но это не меняет факта, что в языке это уже есть)

С недостатков конечно в голос

Да, существенных недостатков по большому счету нет)

Вы забыли про vendor lock и санкции

Вот вы знаете, для тех, кто не работал с джавой десятилетиями (сужу по себе и не только), это одна из причин, почему выбрал го, в итоге, для сайд проекта.

Не смотря на то, что мне нравится Котлин и он мне интуитивно понятен и приятен, на Ktor+ jooq сделал тестово сервис небольшой, все же свобода выбора той же ИДЕ и ресурсов перевесил не в пользу этой экосистемы. Хотя язык мне по своей сути очень зашёл.

Кстати, материалов чисто для бэкенда на мой взгляд меньше, чем на го, но это может и субъективно

Ну и, если честно, смущает, что java и kotlin такие конкурирующие языки, то есть кому-то из них надо доверить свой ценный ресурс - время

Почему у вас есть раздел преимущества Kotlin перед Java, но нет раздела преимущества Java перед Kotlin?

Потому что я отталкивался от Котлин. Но можно перечислить.

public void displayNullable(Optional message) { System.out.println(message.orElse("Нет текста")); }

А если я тут передам null в качестве параметра?
Все равно словите NPE

В java да, будет npe

Я бы выделил ещё scope функции в Котлин, очень удобно и хорошая вариативность в использовании.

scopes: let, run, with, apply, also

а так же холивары в какой ситуации какую из них использовать…

Постепенно приходит понимание, но первое время - да, листик висел с этими it, this.. А так, в первую очередь, стараешься что бы читалось осмысленно.

Да, концептуально это тоже заметный плюс, но по факту это не синтаксис, а стандартная библиотека.

Если ещё по библиотекам и синтаксису - то можно отметить структурные (вложенные) корутины и их удобный синтаксис. В Java подобного синтаксиса нет.

У Kotlin есть и плюсы и минусы перед Java.

Но главная, я бы даже сказал капитальная проблема языка - это то что у него отсутствуют какие бы то ни было весомые киллер фичи отвечающие на вопрос разработчика или компании - зачем на него переходить. Улучшенный синтаксис и встроенные проверки - это вообще не аргумент.

Точнее, не так. У Kotlin была киллер-фича - быть мульти-языком для решения большинства проблем. Другими словами - это должен бы быть единый язык на котором бы писали и фронт и бэк и мобилку. Но идею не вывезли. KotlinJs особо никому не нужен. KMM оказался не лучшей идеей и не взлетел. Остался только KotlinJvm который по сути better java. Раньше хотя бы корутины были преимуществом, но с появление виртуальных потоков и они были нивелированы. Kotlin к сожалению сейчас ничего не может предоставить весомого чтобы било Java и было поводом перейти на этот язык.

Как показало время, как мне кажется, это и стало причиной того что язык взлетел только на андроиде.

На бекенде он тоже используется. Когда только Котлин появился, он закрыл прям заметные проблемы java. Сейчас в java появились аналогичные фичи и в этом немалая заслуга Котлин) а вообще наряду с контролем за null я бы отметил ещё разделение коллекций на изменяемые и неизменяемые.

Я на Java писал 18 лет. На Kotlin пишу последние 5 лет. К мобильной разработке никакого отношения не имею, занимаюсь сугубо бекендом. На Kotlin за 5 лет запустил разработку 4х крупных проектов в качестве техлида. С поиском работы никаких проблем никогда не было. Что я делаю не так?

Kotlin к сожалению сейчас ничего не может предоставить весомого чтобы било Java и было поводом перейти на этот язык.

Не хочу участвовать в холиваре. Но слово "перейти" на мой взгляд это некоторое преувеличение. Kotlin эта та же Java, но просто удобнее. В свои проекты я обычно нанимаю джавистов. Через пару недель после выхода они на Kotlin начинают писать как на Java. Через 3 месяца они на Kotlin пишут как на Kotlin.

@devmark @ermadmi78

Я не говорю что на Kotlin нет проектов или вакансий. Я о том что язык смысл которого был подвинуть Java со своей задачей не справился. Он зашел только на андроиде потому что там бесперспективняк. На бэкенде все очень скромно, особенно учитывая насколько дешево перейти на Kotlin - вся экосистема тажа самая, нужно заменить только язык и все. Но даже при таких благоприятных обстоятельствах и за столько лет Kotlin занимает очень скромную долю рынка. Ладно можно сказать много легаси, но новые проекты тоже продолжают массово стартовать на Java.

А почему так я уже написал - нет каких то серьезных позиций где Kotlin бы мог то что не может Java. Рантайм такой же, библиотеки такие же в большинстве. Корутины уже не преимущество. По производительности Kotlin даже чуть проигрывает Java. Остаеться чуть лучше синтаксис, закрытие какие то проблем да, чуть понадежнее да. Кому то норм, а кому то из разрабов будет влом забивать себе голову еще одним языком который чуть лучше. Многим компаниям, как выясняется, тоже влом заморачиваться с поиском котлинистов или переучиванием джавистов. Оно бы можно было, если была киллер фича, которая бы это оправдывала, но ее нет.

Хороший пример Go. У языка огромное количество проблем, но есть несколько киллерфич, за счет которых он взлетел, которые выделяют его на фоне других и которые являются аргументом для команды и компании, даже не смотря на то что там вообще отдельная молодая экосистема.

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

Ну, подвинуть Java - это изначально не реалистичная цель была. А вот создать весьма и весьма достойную альтернативу Java - ИМХО, получилось. Я искренне люблю и уважаю Java, но пишу на Kotlin. Так как он мне нравится ещё больше, чем Java :)

Ну, подвинуть Java - это изначально не реалистичная цель была.

Вполне реалистичная. На том же андроиде Kotlin вообще вытеснил Java. Другой пример, как я уже писал - Go. Язык, у которого куча детских болячек, у которого не было ни экосистемы нормальной ни даже пакетного менеджера, плюс который откровенно недолюбливали многие за его примитивность. Т.е. по сравнению с Kotlin у которого на старте была уже вся экосистема и инструменты, там вообще все плохо. И тем не менее, он взлетел и откуси не то что у Java а у всего пула backend языков не слабый кусок рынка.

И вот получается, есть красивый милый приятный современный Kotlin с весьма скромными результатами на уровне приза зрительских симпатий. А есть кривой косой морально устаревший Go который при этом подвинул рынок. И еще раз повторю - все потому что Go было что предложить рынку кроме своей приятности а Kotlin - нет.

Это я не к тому что не люблю Kotlin а к тому - почему для этого языка дела сейчас обстоят так как обстоят.

В целом понимаю вашу точку зрения. И хочу дополнить, что Kotlin на Android взлетел благодаря поддержке со стороны Google.

Поэтому теперь, если метод принимает в качестве параметра read-only List, я могу быть уверен, что внутри он ее точно не изменит.

Всё же уверенным быть нельзя - можно только надеяться:

fun processDigits(digits: List<Int>) {
    if (digits is MutableList<Int>) {
        digits.add(0)
    }
}

fun main() {
    val digits = mutableListOf(1, 2, 3) // MutableList<Int>
    processDigits(digits)
    println(digits) // [1, 2, 3, 0]
}

Если мы хотим выстрелить себе в ногу, то никто нам не может помешать)

Такие конструкции это всё-таки плохой код (мягко говоря), потому что мы нарушаем инкапсуляцию и полиморфизм. Тут речь больше про контракт: если я вижу, что метод принимает read-only list, значит метод декларирует, что он не собирается менять этот список.

Не соглашусь в части того что нарушено. Нарушения полиморфизма здесь нет, инкапсуляцию нарушает сам Котлин давая такую возможность.

А что нарушено так это принцип подстановки Лисков, которые говорит что поведение функции должно оставаться стабильным при передаче любого из наследников класса. Что очевидно нарушается в этом коде, сколько поведение зависит от того, какой именно наследник передан.

Вряд ли кому-то сейчас придёт в голову писать на Java такой код:

public static void main(String[] args){String text="Hello!";System.out.println(text);}

А вот и нет! Мне пришло. Сижу периодически на платформе codingame когда делать нечего. Иногда там встречается соревнование "кто короче напишет" - подсчёт идёт в символах. Удаление всех пробелов очень спасает, иногда даже короче получается, чем у некоторых питонистов. Так что это определённо важная фича, а вы её назвали бесполезной...

if (message != null) {

System.out.println(message);

} else {

System.out.println("Нет текста");

}

Это не эквивалент решения, которое вы предоставили на котлине. В джаве есть тернарные операторы и всё это записывается также в одну строчку.

К чему вся эта игра слов?

А почему нет? Это не плюс на самом деле... Это даже скорее минус, что ты не можешь видеть, от чего ты наследуешься: от класса или метода.

В Kotlin есть механизм интерполяции строк, когда мы можем подставлять переменную непосредственно в строку с помощью знака доллара ($). Если над переменной при этом нужно выполнить еще какое-то действие (например, прибавить 1), вся конструкция заключается в фигурные скобки

thymeleaf на минималках какой-то... Польза от того сомнительная, но окэй.

На практике checked-исключения скорее мешают, чем помогают

Товарищ, вы боритесь менее, чем за 1 строку кода! Остановитесь! Разработчику полезно знать, где вообще подобный эксепшон в перспективе может появиться.

В конце статьи вы таки вспомнили о наличии тернарного оператора. Но уже слишком поздно. Итого получается, что весомых аргументов тупо нет. Кроме, возможно, защиты от NPE. А ещё вы, по моему мнению, несколько пренебрегаете преимуществами джавы.

Товарищ, вы боритесь менее, чем за 1 строку кода! Остановитесь! Разработчику полезно знать, где вообще подобный эксепшон в перспективе может появиться.

Я сам не джавист, но всё же условно в вузе с джавой мы работали и за это время я заметил маленький минус у такого подхода. Условно я не могу написать так:

Function<A, B> f = this::someMethodThatThrows;

По этому мне придётся оборачивать:

Function<A, B> f = a -> {
  try {
    someMethodThatThrows(a);
  } catch (Exception e) {
    throw RuntimeException(e);
  }
};

Я всё же считаю, что такое оборачивание является некоторой проблемой и не так далеко ушло от какого-то err != nil в go — хоть и не нужно так часто.

Не согласен, чекед исключение - это аналог Result<B, BaseError>.

Function<A, B> f = a -> {
  var res = someMethodThatErrs(a);
  if (res.hasError()) throw new...
  
  return res.value;
}

В лучшем случае, в худшем if (res.error instanceof ParseError)

Те же яйца, вид в профиль.

А для if(res.hasError()).... В Котлин добавили библиотеку с Error монадой, криво косо, но добавили.

Без синтаксического сахара больно смотреть правда...

Может быть, всё же дело в том, что я не джавист и джавовские практики мне не знакомы. Если так рассудить, явные исключения действительно схожи с Result, а неявные с panic. Но, в какой-то мере, мне кажется, что проблема исключений в некоторой степени и в том, что ты с ними работать будешь как с исключениями. Возможно, было бы удобно всё же сделать какой-то Result типа такого, чисто чтобы что-то делать локально внутри функции и локально с результатом конкретной функции — хотя это, наверное, и грозит потерей стектрейса (или нет, я не помню, как это работает).


public sealed interface Result<T, E extends Exception> {
    record Ok<T, E extends Exception>(T value) implements Result<T, E> {
        public T unwrap(){
            return value;
        }

        public T rethrow() {
            return value;
        }

        public <T0> Ok<T0, E> map(Function<T, T0> fn) {
            return new Ok<>(fn.apply(value));
        }

        //and other
    }
    record Err<T, E extends Exception>(@NotNull E err) implements Result<T, E> {
        public T unwrap(){
            throw new RuntimeException(err);
        }

        public T rethrow() throws E {
            throw err;
        }

        @SuppressWarnings("unchecked")
        public <T0> Err<T0, E> map(Function<T, T0> fn) {
            return (Err<T0, E>)this;
        }

        //and other
    }
    @FunctionalInterface
    interface ThrowingFn<T, E extends Exception>{
        T run() throws E;
    }

    @SuppressWarnings("unchecked")
    @NotNull
    static<T, E extends Exception> Result<T, E> catch_result(ThrowingFn<T, E> fn) {
        try {
            return new Ok<>(fn.run());
        } catch (Exception e) {
            return new Err<>((E)e);
        }
    }

    static<T> T unwrap_result(ThrowingFn<T, ? extends Exception> fn) {
        try {
            return fn.run();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    T unwrap();
    T rethrow() throws E;
    <T0> Result<T0, E> map(Function<T, T0> fn);

    //and other
}

Во всяком случае, я думаю, что есть пару вещей, которые изменить бы хотелось, чтобы всё работало приятнее:

  • Синтаксис

    Условный try{ } catch(ExceptionType e) {} лично для меня имеет пару проблем в дизайне:

    1) Фигурные скобки вокруг try и catch обязательные — рассчитаны лишь на то, чтобы оборачивать всю функцию — при необязательности для остальных конструкций.

    2) Тип исключения — если throws функции лишь одного типа, тип в catch можно бы и вывести из контекста

    3) Блок try всегда возвращает void — нужно заводить переменную вне блока для результата.

    4) Сахар на try{ } catch(ExceptionType e) {throw new RuntimeException(e)} всё же был бы приятен

  • Неявность и схожесть с неявными исключениями — поставь throws Exception на функцию — и не заметь throw там, где ты уже хочешь его поймать.

  • Не помешали бы существующие отдельно методы, кидающие явные и неявные исключение в тех случаях, когда принято кидать лишь неявные.

  • Неудобность с точки зрения типизации. Опять же, условный Function<A, B> уже запрещает кидать явные эксепшены. Если бы явные исключения становились частью возвращаемого типа, было бы удобнее. Хотя и можно сделать условный ThrowingFunction<ArgT, ResT, ExT extends Exception>, навроде того, что я написал сверху, но так-то большинству библиотек и фреймворков всё же будет всё равно.

Но может быть и такое, что это всё вообще не нужно, всё и так работает замечательно, я не прав и у меня мозг просто немного оrustенел, так сказать.

А вот и нет! Мне пришло. Сижу периодически на платформе codingame когда делать нечего. Иногда там встречается соревнование "кто короче напишет" - подсчёт идёт в символах. Удаление всех пробелов очень спасает, иногда даже короче получается, чем у некоторых питонистов. Так что это определённо важная фича, а вы её назвали бесполезной...

Данную статью я писал точки зрения промышленной разработки больших корпоративных проектов (основная ниша java и kotlin). Там всё-таки код в одну строку не пишут.

А почему нет? Это не плюс на самом деле... Это даже скорее минус, что ты не можешь видеть, от чего ты наследуешься: от класса или метода.

По поводу наследования, в процессе agile-разработки очень часто возникает ситуация, что интерфейс превращается в абстрактный класс или наоборот. Вот эти все extends и implements в таком случае особой ценности не несут.

thymeleaf на минималках какой-то... Польза от того сомнительная, но окэй.

Как человек, активно использующий thymeleaf в некоторых проектах, могу вас заверить, что котлиновская интерполяция строк поприятнее, т.к. она мощнее.

Товарищ, вы боритесь менее, чем за 1 строку кода! Остановитесь! Разработчику полезно знать, где вообще подобный эксепшон в перспективе может появиться.

В том-то и дело, что не одну) Очень часто вереница checked-эксепшенов занимает несколько строк. Особенно при использовании автоформатирования.

Возможно у нас с вами разный опыт, но именно "вереницу checked-эксепшенов" я встречаю в коде очень редко, а уже так чтобы она занимала больше двух строк (начиналась на строк объявления функции, занимала полностью ещё одну отдельную, и требовала ещё как минимум одну строку) - это и вовсе практически нонсенс.

Большое кол-во исключений в сигнатуре может быть в сервисных методах самого верхнего уровня, т.к. они могут объединять все исключения с более низких уровней. Но мы конечно всегда можем просто написать throws Exception и не париться)

Да, на верхнем уровне исключения часто группируются, но не до уровня Exception, а до базового класса библиотеки.

Что касается checked-исключений, это конечно древний костыль, но костыль легко обходимый без смены языка. В новом коде можно просто их не писать, а для вызова методов с throws существует zero-cost (ну, почти zero) хак:

@SuppressWarnings("unchecked")
static <T extends Throwable> void throwAny(Throwable t) throws T {
  throw (T) t;
}

И теперь можно откуда угодно делать

try {
  foo(); // throws smt
} catch (Throwable e) {
  throwAny(e);
}

Вуаля, проблема решена. Ну, или можно пользоваться checked-фичей, как задумано. Тоже как вариант.

P.S. В случае с InterruptedException я бы даже сказал, что это плюс - такая себе жесткая напоминалка не забыть флаг прерывания.

Сравним метод на Java, печатающий в консоли строку текста: ...

Можно также лаконично написать на java:
public void displayNullable(String message) {

System.out.println(message != null ? message : "Нет текста");    

}

В Kotlin меня радует, что я могу определить привычные операторы для собственных классов. Это повышает читаемость кода.

Очень смело, конечно, заявлять, что переопределение операторов повышает читаемость кода :)

Операторы очень выручают при работе со стандартной библиотекой. Я могу использовать математические операторы для работы с числами BigDecimal:

val a = BigDecimal("100.00")
val b = BigDecimal("200.00")
val c = BigDecimal("300.00")
val sum = a * b + c

// против Java-варианта:
BigDecimal sum = a.multiply(b).plus(c);

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

То же самое я могу сделать для своего собственного класса, например, для сложения матриц.

При этом в котлине я не могу определять вообще произвольные комбинации символов как операторы. А только фиксированный набор стандартных операторов.

После появления виртуальных потоков в JVM, Java развивает идею Scoped Values и Structured Concurrency JEP`s.
Сложно представить, что условный Netflix будет использовать корутины. Значит Kotlin будет подстраивать свое API и нужно ждать интеграции пока StructuredTaskScope завернут в CoroutineScope с исключениями, завершением задач и пр. А Java еще на шаг вперед уйдет.
Плюс вопрос усилий, нужно ли это авторам Kotlin, или они вполне логично сосредоточат силы на Android/JS в будущем.

Чтобы заоаботать , нужно создать спрос. "Делаем Kotlin, оставляем его нормальную поддержку только в IDEA, profit".

null-контроль во всех JVM-языках работает ровно для момента, когда требуется интероперабельность с Java. Вызываете метод Java, и вы уже точно не знаете, вернется null или нет. С одной стороны, null нужно подозревать всегда, с другой даже в Java есть методы, которые никогда null не возвращают. Тони Хоар, человек, придумавший null, очень раскаивался в этом.

Исключения (и checked, и unchecked) - ещё одна родовая травма Java. И все JVM-языки вынуждены как-то иметь с ними дело. Показательно, что в изначально таком чисто Java-проекте, как Spring, от checked отказались.

По поводу if ... else против тернарного оператора и return имею противоположную точку зрения: if ... else читабельнее, а return лучше вообще не использовать. Return лишь немногим лучше goto, как и break, и прочие "прерыватели" логики функций.

По поводу интеропа с java, мы стараемся у себя в проектах не смешивать java и kotlin. То есть если пишем на Kotlin, то все исходники должны быть на Kotlin (в том числе юзаем build.gradle.kts вместо грувишного buld.gradle). Но при этом мы активно используем Spring и уже знаем, где могут возникать null при вызове стандартных компонентов, а где не могут. На самом деле, если конфиг правильный, то в большинстве случаев у нас будет создан какой-то инстанс. А если нет - мы узнаем об этом ещё при старте приложения.

Забыли сказать про то, что в котлине куча удобных методов для работы с коллекциями, котлин уменьшает кол-во скобок благодаря удобному объявлению и использованию лямбд ( list.forEach { printlin("item: $it") }; map.forEach { k, v -> println("$k: $v")} ), у котлина человеческий when (хотя в новых джавах что-то подобное уже в switch добавили), не надо писать этот дурацкий new, можно ещё свойства-расширания делать, что как и функции-расширения позволяет чейнить вызовы, а не оборачивать в скобки в обратном порядке, есть корутины, есть object Obj { }, вызов функции с именованными параметрами myFun(cnt = 10, name = "n"), inline fun, ranges (1..10), спасибо, что не надо париться между примитивами и их обёртками (Int для int & Integer), всякие if-else, try-catch, when могут возвращать значение, when { a -> {}, b -> {}, else -> {} } можно использовать как замену if-else. И тут я наверняка ещё в 2 раза больше могу написать, но тут уже всего не упомнишь. Так что вам ещё предстоят открытия :).

Для меня из недостатков - это выпиленный for (;;). Отсутствие тернарников скорее хорошо, чем плохо, потому что они читабельны, если однострочны, чаще же всего все эти тернарники впоследствии разрастаются и лучше писать if-else или when.

Спасибо за дополнение! В Kotlin работа с лямбдами действительно удобна. Однако ими тоже не следует злоупотреблять: большое количество вложенных друг в друга лямбд порождают "лесенку" в коде.

Цикл for очень удобен при "низкоуровневом", алгоритмическом программировании. Особенно когда у нас кастомный алгоритм обхода коллекции, а не банальный инкремент. Но в типовых приложениях чаще всего мы работаем с коллекциями и чаще всего перебираем элементы по очереди от начала до конца. Поэтому видимо авторы и решили оставить только for-each.

Странно, что забыли намного более удобно организованную работу с методами/функциями

Именованные параметры позволяют не вспоминать, в каком же порядке и что значат эти 5 строковых параметров в методе стандартной либы, плюс страхуют от ошибок формата "поменял местами аргументы метода", так как от их порядка ничего зависеть не будет в отличие от Java

Ну и приятная мелочь в виде значений по умолчанию тоже делает написание кода приятнее и удобнее

Полностью согласен! Я хотел про это написать и действительно забыл) Однако тут есть и обратная сторона медали, как и в случае с возвращаемым значением: с точки зрения единообразия в команде надо договориться, в каких случаях делаем именованные параметры, в каких - не делаем. Или всегда делаем.

Забыли возможность возврата значения из блоков if и try. Удобно же.
И одна из киллерфич - мультиплатформа + мультиплатформенный compose.
В одном проекте - браузер (wasm) / сервер(jvm) / мобила (android).

Возврат значений из управляющих конструкций - да, это удобно. Однако я не назвал бы это киллер фичой. Особенно если вспомнить, что это увеличивает количество возможных стилей написания методов. Скорее, приятный бонус. Мультиплатформа концептуально да, но она как будто не взлетела(

Про киллерфичу я имел в виду именно мультиплатформу (то, чего точно нет в Яве. TeaVM, думаю, ещё больше нишевая вещь). И, наверное, неполно выразился. Не только мультиплатформа, а в плюсе с "фуллстековостью". Возможность писать вебку на чистом котлине, с использованием общих core-модулей с сервером и клиентом.
Насчёт "не взлетела" - не могу спорить. Широты она может не отхватила, однако в продакшене у меня, например, уже вторая версия.
Но это история больше для маленьких команд, у которых нет ресурсов на отдельных фронтовиков/мобильников.

Я нисколько не пытаюсь принизить значимость мультиплатформы, но мне особо не приходилось слышать об успешных кейсах ее применения на практике. Буду признателен, если поделитесь своим. Да и на бэке Котлин до сих пор внедряется не так активно, как хотелось бы.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Информация

Сайт
www.raiffeisen.ru
Дата регистрации
Дата основания
1996
Численность
5 001–10 000 человек
Местоположение
Россия