LINUX.ORG.RU

Вышел Kotlin 1.0

 , ,


2

4

После многих лет разработки вышла стабильная версия языка Kotlin 1.0.

Kotlin — это язык программирования, разрабатываемый компанией JetBrains, компилируемый в JVM байткод. Язык комбинирует ОО и функциональные подходы, и фокусируется на интероперабельности c Java, безопасности, ясности кода и инструментальной поддержке.

Kotlin является языком общего назначения и работает везде, где работает Java: серверные приложения, мобильные приложения (Android), десктопные приложения.

От себя можно добавить что Kotlin это «улучшенная Java», язык вобравший в себя полезные элементы из других языков (таких как C#). При переходе на Kotlin, существенно уменьшается объем «java лапши» в коде.

Исходный код проекта доступен на github.

Попробовать язык без установки можно здесь.

>>> Подробности

★★

Проверено: maxcom ()
Последнее исправление: maxcom (всего исправлений: 4)
Ответ на: комментарий от Legioner

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

GblGbl ★★★★★
()
Ответ на: комментарий от kazufukurou

a != null && a.b != null && a.b.c != null

Если тебе приходится писать такие конструкции, ты определенно делаешь что-то не так.

GoodPerson
()
Ответ на: комментарий от kazufukurou

Optional почти то же самое, но это выглядит удобнее.

GblGbl ★★★★★
()
Ответ на: комментарий от GoodPerson

Например есть класс, в который десериализуется сложный вложенный json от сервера. Сервер может вернуть null на любом уровне вложенности. Как предлагаешь избежать проверок?

kazufukurou
()
Ответ на: комментарий от GblGbl

Например? Что там есть такого, что вызывает непреодолимое желание на него переползти?

Крупные плюсы: null-safety, properties, val, when, хороший API для работы с коллекциями, data-классы, operator overloading, отсутствие checked exceptions, this-коллбэки (такого я вообще ни в одном языке не видел, шикарное изобретение), extensions, вложенные функции, destructuring, правильно перегруженный ==.

Огромный плюс в сравнение со всеми остальными JVM-языками — очень прозрачная интеграция с Java-кодом. По сути тут я видел единственную проблему — по умолчанию в Kotlin классы final и всякие аспектные библиотеки не могут от них отнаследовать свою проксю (реально это проблема этих библиотек, конечно, но кому от этого легче). Больше проблем нет. Использовать из Kotlin любую библиотеку не сложнее, чем из Java и наоборот — использовать любой Kotlin-код из Java очень просто.

Минус я могу сказать только один: нет try-with-resource. Есть ограниченная имитация через лямбды, но она неудобна, когда ресурсов много.

Legioner ★★★★★
()
Ответ на: комментарий от kazufukurou

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

GoodPerson
()
Ответ на: комментарий от GoodPerson
String json = getJson();// {"a":{"b":{"c":{"d":"value"}}}} или что угодно
MyClass m = new Gson().fromJson(json, MyClass.class);
String value = m.a.b.c.d; // NPE

class MyClass {
    A a;
}

class A {
    B b;
}

class B {
    C c;
}

class C {
    String d;
}

Что я делаю не так? И как это написать по-человечески?

kazufukurou
()
Ответ на: комментарий от kazufukurou

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

        String value = m.getA().flatMap(A::getB).flatMap(B::getC).flatMap(C::getD).orElse(null);

class MyClass {
    private A a;

    public Optional<A> getA() {
        return Optional.ofNullable(a);
    }
}

class A {
    private B b;

    public Optional<B> getB() {
        return Optional.ofNullable(b);
    }
}

class B {
    private C c;

    public Optional<C> getC() {
        return Optional.ofNullable(c);
    }
}

class C {
    private String d;

    public Optional<String> getD() {
        return Optional.ofNullable(d);
    }
}

Legioner ★★★★★
()
Ответ на: комментарий от tailgunner

И чем это лучше null?

Читать проще, все действия выписываются линейно, а не в виде гигантского дерева if-ов, в котором опечататься — как раз плюнуть.

Ну и забыть проверить на наличие значения становится сложней.

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 1)
Ответ на: комментарий от Legioner

все действия выписываются линейно, а не в виде гигантского дерева if-ов, в котором опечататься — как раз плюнуть

Мне кажется, эта длинная макаронина с flatMap не лучше кучи выражений в if.

tailgunner ★★★★★
()
Ответ на: комментарий от Legioner

this-коллбэки (такого я вообще ни в одном языке не видел, шикарное изобретение)

Можно ссылочку на описание? Дабы самому в доках не искать.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Описание, пример, как можно использовать. Вкратце — можно объявить, что функция принимает параметром другую функцию, при вызове которой this будет установлен на объект определённого типа. При написании этой второй функции (как правило в виде анонимной лямбды) можно использовать поля и методы этого объекта так, как будто эта функция является его членом. По сути простой сахар. Но безумно удобный для builder-ов и некоторых других применений.

Пример:

    fun buildString(builderAction: StringBuilder.() -> Unit): String = 
            StringBuilder().apply(builderAction).toString()

    val str = buildString {
        append("abc")
        append(123)
        append("def")
    }

аналог на Java:

    String buildString(Consumer<StringBuilder> builderAction) {
        StringBuilder stringBuilder = new StringBuilder();
        builderAction.accept(stringBuilder);
        return stringBuilder.toString();
    }

        String str = buildString(sb -> {
            sb.append("abc");
            sb.append(123);
            sb.append("def");
        });

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 2)
Ответ на: комментарий от Legioner

Напоминает приемы метапрограммирования из Ruby (это про пример с html-билдером из документации).

eao197 ★★★★★
()
Ответ на: комментарий от Legioner

Естественно в реальности там скорее всего не будет null, но от ошибки никто не застрахован.

kazufukurou
()
Ответ на: комментарий от kazufukurou

Ты не понял, такие обороты вообще не должны быть написаны, язык не при чем.

GoodPerson
()
Ответ на: комментарий от kazufukurou

Из-за этого выпилили ternary operator, вместо него предлагают юзать уродливый if … else …

I60R ★★
()
Последнее исправление: I60R (всего исправлений: 1)
Ответ на: комментарий от Legioner

Спасибо за пример. Точно такая фича есть в groovy, а вот в Scala нет. Мне не хватало когда я свой DSL писал на Scala. Буду знать что в Kotlin есть.

voronaam ★★
()
Ответ на: комментарий от maxcom

В случае с Kotlin дело не только в том, что можно не писать «sb.», а в том, что код исполняемый внутри лямбды будет исполняться в определенном контексте, окруженный определенными конкретными элементами.

Например для работы с sqlite базой на андроиде, если мы хотим облегчить обертку в транзакции, вместо Java кода

db.beginTransaction()
try {
   db.delete("users", "first name = ?", new String[] { "Jake" });
   db.setTransactionSuccessful();
} 
finally {
   db.endTransaction();
}

Можно определить extension-метод:

inline fun SQLiteDatabase.inTransaction(func: SQLiteDatabase.() -> Unit) 
{
   beginTransaction()
   try {
      func()
      setTransactionSuccessful()
   } 
   finally {
      endTransaction()
   }
}

И потом использовать его вот так:

db.inTransaction {
   delete("users", "first name = ?", arrayOf("Jake" ));
}

Существенно упрощает жизнь, куда меньше шансы что в одном каком-то конкретном месте будет забыт вызов или случайно порядок выйдет не правильный. При этом в плане байткода скомпилированного код выходит 1-в-1 такой-же что и оригинальный код на Java (для этого inline там).

Или можно например создать класс-враппер, который будет гарантировать что доступ к внутреннему обьекту можно получить только заблокировав его, тем самым исключая случайный доступ без блокировки:


data class Lock<T>(private val obj: T) 
{
   public fun acquire(func: (T) -> Unit)
   {
      synchronized (obj) {
         func(obj)
      }
   }
}

val readerLock = Lock(JsonReader(stream))

readerLock.aquire {
   println(it.readString())
}

от «it» внутри последней лямбды я специально не стал избавлятся, это можно сделать если заменить

public fun acquire(func: (T) -> Unit)

на

public fun acquire(func: T.() -> Unit)
qrck ★★
() автор топика
Последнее исправление: qrck (всего исправлений: 3)
Ответ на: комментарий от qrck

Эти обе задачи в Scala решены через call by name параметры и implicit'в.

maxcom ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.