Почему стоит полностью переходить на Ceylon или Kotlin (часть 1)

В последнее время активную популярность набирает Kotlin. А что если попробовать выбрать более экзотические языки, и применить к ним те же аргументы? Статья написана по мотивам этой, практически повторяя все аргументы за Kotlin. Основная задача: показать, что Ceylon может практически тоже самое, что и Kotlin, применительно к Java. Но кроме этого у Ceylon есть кое-что еще, что будет описано в следующей статье.


Хочу рассказать о новом языке программирования, который называется Ceylon, и объяснить, почему вам стоит использовать его в своём следующем проекте. Раньше я писал на Java (много и долго, более 10 лет, начиная с Java 1.4 и заканчивая Java 8), и Java мне нравилась. Затем на меня большое впечатление произвела Scala, в результате чего Java как язык стал любить несколько меньше. Но судьба свела меня с языком Сeylon, и в последние полтора года мы пишем на Ceylon везде, где только можно. В реальных коммерческих проектах, правда внутренних. И в данный момент я не представляю себе ситуации, в которой лучше было бы выбрать Java, я не рассматриваю Java как язык, на котором стоит начинать новые проекты.


Ceylon разработан в Red Hat, автор языка — Gavin King, известный по такому фреймворку как Hibernate. Он создавался людьми, которые хорошо понимают недостатки Java, основная цель заключалась в решении сугубо прикладных задач, обеспечение максимально легкой читаемости кода, избегание любых неоднозначностей и подводных камней, во главу всего стала предсказуемость и структурная красота языка. Также большое внимание уделялось приемлемому времени компиляции. В настоящее время версия языка 1.3.2, непосредственно я познакомился с языком, когда вышла версия 1.2.0.


Хотя Ceylon компилируется в JavaScript, я сконцентрируюсь на его первичной среде — JVM.


Итак, несколько причин, почему вам следует полностью переходить на Ceylon (порядок совпадает с одноименными пунктами соответствующей Kotlin статьи):


0# Совместимость с Java


Также, как и Kotlin, как и Scala, Ceylon на 100 % совместим с Java. Вы можете в буквальном смысле продолжать работать над своим старым Java-проектом, но уже используя Ceylon. Все Java-фреймворки также будут доступны, и, в каком бы фреймворке вы ни писали, Ceylon будет легко принят упрямым любителем Java. Можно без проблем вызывать из Java Ceylon код, также без проблем вызывается Java код.


1# Знакомый синтаксис


Одна из основных особенностей языка Ceylon — максимально удобно читаемый для существующих разработчиков синтаксис. Если взять существующего Java разработчика, то с пониманием Ceylon синтаксиса у него не будет ни малейших проблем. Даже такие языки, как Scala и Kotlin будут менее похожи на Java. Ниже приведен код, показывающий значительное количество конструкций языка, аналогичный примеру на Kotlin:


class Foo(String a) {

    String b= "b";           //  unmodifiable
    variable Integer i = 0;  // variable means modifiable

    void hello() {
        value str = "Hello";
        print("``str`` World");
    }

    Integer sum(Integer x, Integer y) {
        return x + y;
    }

    Float maxOf(Float a, Float b) => if (a > b) then a else b
}

Соответственно можно без проблем продолжать писать в Java стиле на Ceylon.


2# Интерполяция строк


Это как бы более умная и читабельная версия String.format() из Java, встроенная в язык:


value x = 4;
value y = 7;
print("sum of ``x`` and ``y`` is ``x + y``") ; // sum of 4 and 7 is 11

ИМХО синтаксис здесь будет поприятнее, чем в Kotlin, с Java даже не хочется сравнивать.


3# Выведение типа


Ceylon будет выводить ваши типы, если вы посчитаете, что это улучшит читабельность:


value a = "abc";                         // type inferred to String
value b = 4;                             // type inferred to Integer

Float c = 0.7;                   // type declared explicitly
List<String> d = ArrayList<String>();     // type declared explicitly

4# Умные приведения типов (Smart Casts)


Компилятор Ceylon отслеживает вашу логику и по мере возможности автоматически выполняет приведение типов, т. е. вам больше не нужны проверки instanceof после явных приведений:


if (is String obj) {
    print(obj.uppercased)     // obj is now known to be a String
}

5# Интуитивные равенства (Intuitive Equals)


Можно больше не вызывать явно equals(), потому что оператор == теперь проверяет структурное равенство:


value john1 = Person("John"); //we override equals in Person
value john2 = Person("John");
print(john1 == john2);    // true  (structural equality)
print(john1 === john2);    // false  (referential equality)

6# Аргументы по умолчанию


Больше не нужно определять несколько одинаковых методов с разными аргументами:


void build(String title, Integer width = 800, Integer height = 600) {
    return Frame(title, width, height);
}

7# Именованные аргументы


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


build("PacMan", 400, 300)                           // equivalent
build {title = "PacMan"; width = 400; height = 300;}  // equivalent
build {title = "PacMan"; height = 300;}  // equivalent with default width

8# Выражение switch


Оператор ветвления заменён гораздо более читабельным и гибким в применении выражением switch:


switch (obj)
case(1)                              { print("x is 1"); }
case(2)                              { print("x is 2"); }
case(3 | 4)                          { print("x is 3 or 4"); }
case(is String)                      { print ("x is String"); }
case([Integer a, Float b, String c]) {print ("x is tuple with Integer ``a``, Float ``b`` and String ``c``");}
else                                 { print("x is out of range");}

switch может работать как выражение, также результат switch может быть присвоен переменной:


Boolean|IllegalStateException res = 
    switch(obj)
    case(null) false
    case(is String) true
    else IllegalStateException();

Это не полноценный pattern matching, но для большинства случаев хватает и текущего функционала.


В отличие от Kotlin у Ceylon требуется, чтобы к switch все условия были disjoint, то есть не пересекались, что для switch гораздо более логично. Если требуется сопоставление по диапазону или условия могут пересекаться, то нужно использовать обычный if.


9# Свойства


Можно добавить публичным полям кастомное поведение set & get, т. е. перестать набивать код безумными геттерами и сеттерами.


class Frame() {
    variable Integer width = 800;
    variable Integer height = 600;

    Integer pixels => width * height;
}

10# Data Class


К сожалению данного функционала пока нет. Очень хотелось бы иметь иммутабельные классы, у которых автоматом переопределен toString(), equals(), hashCode() и copy(), но, в отличие от Java, не занимали 100 строк кода.


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


class Person(shared String name, 
             shared String email,
             shared Integer age) extends DataObject() {}

value john = Person("John", "john@gmail.com", 112);
value johnAfterBirhstday = john.copy<Person>({`Person.age`->113;});
assertEquals(john, john.copy<Person>());
assertEquals(john.hash, john.copy<Person>().hash);

То есть на уровне библиотек получилось переопределить toString, оставить класс иммутабельным, мы получили возможность создавать клоны и изменениями отдельных аттрибутов. К сожалению работает это не так быстро, как могло быть, если бы поддержка была в языке. И нет проверки типов во время компиляции = если мы склонируем с переопределениев возраста и в качестве значения укажем строку, получим ошибку в рантайме. То, что такого функционала пока нет — безусловно плохо. Но то, что нужный функционал при необъодимости можем написать самостоятельно на уровне библиотеки — это очень хорошо.


11# Перегрузка оператора (Operator Overloading)


Заранее определённый набор операторов, которые можно перегружать для улучшения читабельности:


class Vec(shared Float x, shared Float y) satisfies Summable<Vec> {
    shared actual Vec plus(Vec v)  => Vec(x + v.x, y + v.y);
}

value v = Vec(2.0, 3.0) + Vec(4.0, 1.0);

12# Деструктурирующие объявления (Destructuring Declarations)


Некоторые объекты могут быть деструктурированы, что бывает полезно, к примеру, для итерирования map:


for ([key -> [val1, val2, val3]] in map) {
    print("Key: ``key``");
    print("Value: ``val1``, ``val2``, ``val3``");
}

13# Диапазоны (Ranges)


Для улучшения читабельности:


for (i in 1..100) { ... } 
for (i in 0 : 100) { ... }
for (i in (2..10).by(2)) { ... } 
for (i in 10..2) { ... }  
if (x in 1..10) { ... }

В отличие от Kotlin обошлось без ключевого слова downTo.


14# Функции-расширения (Extension Functions)


Их нет. Возможно появится, в ранних спецификациях языка такая возможность рассматривалась. Но вместо функций расширений в принципе работают top level функции. Если мы, допустим, хотим добавить к классу String метод sayHello, то "world".sayHello() выглядит не намного лучше чем sayHello("world"). В будущем они могут появиться.


В принципе соответствующие функции, доступные для класса, позволяет находить сама IDE, иногда это работает.


15# Безопасность Null


Java следует называть почти статично типизированным языком. Внутри него переменная типа String не гарантированно ссылается на String — она может ссылаться на null. И хотя мы к этому привыкли, это снижает безопасность проверки на статичное типизирование, и в результате Java-разработчики вынуждены жить в постоянном страхе перед NPE.


В Ceylon эта проблема решена посредством разделения на типы, допускающие и не допускающие значение null. По умолчанию типы не допускают null, но их можно преобразовать в допускающие, если добавить ?:


variable String a = "abc";
a = null;                // compile error

variable String? b = "xyz";
b = null;                // no problem

За счет функционала union types String? это просто синтаксический сахар для String|Null. Соответственно можно написать:


variable String|Null с = "xyz";
с = null;                // no problem

Ceylon заставляет вас бороться с NPE, когда вы обращаетесь к типу, допускающему null:


value x = b.length        // compile error: b might be null

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


if (!exists b) { return; }
value x = b.length        // no problem

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


value x = b?.length;       // type of x is nullable Int

Можно объединять безопасные вызовы в цепочки, чтобы избегать вложенных проверок если-не-null, которые иногда мы пишем в других языках. А если нам по умолчанию нужно не null-значение, то воспользуемся elvis-оператором else


value name = ship?.captain?.name else "unknown";

Если всё это вам не подходит и вам совершенно точно нужны NPE, то скажите об этом явно:


value x = b?.length else NullPointerException()  // same as below
assert(!NullPointerException x);

16# Улучшенные лямбды


Это хорошая система лямбд — идеальный баланс между читабельностью и лаконичностью благодаря нескольким толковым решениям. Синтаксис прост:


value sum = (Integer x, Integer y) => x + y;  // type: Integer(Integer, Integer)
value res = sum(4,7)                      // res == 11

Соответственно синтаксис может быть:


numbers.filter( (x) => x.isPrime() );
numbers.filter(isPrime)

Это позволяет нам писать лаконичный функциональный код:


    persons
        .filter ( (it) => it.age >= 18)
        .sort(byIncreasing(Person.name))
        .map ( Person.email )
        .each ( print );

Система лямбд плюс синтаксические особенности языка, делает Ceylon неплохим инструментом для создания DSL. Пример DSL, похожего на Anko, в синтаксисе Ceylon:


 VerticalLayout {
    padding = dip(30);  {
    editText {
        hint = "Name";
        textSize = 24.0;
    },
    editText {
        hint = "Password";
        textSize = 24.0;
    },
    button {
        "Login";
        textSize = 45.0;
    } }
};

17# Поддержка IDE


Между прочим, она достаточно неплохая. Есть eclipse плагин, есть IDEA плагин. Да, по части фич и багов все несколько хуже, чем в Scala или Kotlin. Но в принципе работать можно и достаточно комфортно, проблемы IDE на скорости разработки практически не сказываются.


Итого, если брать сильные стороны Kotlin, Ceylon уступает Kotlin отсутствием функционала DataObject (который можно эмулировать самостоятельно средствами библиотек). В остальном он обеспечивает не меньшие возможности, но с более приятным для чтения синтаксисом.


Ну и так же, как и на Kotlin, на Ceylon можно писать для Android.


Прочитав вышесказанное, может сложиться впечатление — а зачем нам это? Тоже самое есть и в Kotlin, практически 1 в 1.


А то, что в Ceylon есть вещи, которых нет ни в Kotlin, ни в Scala, и за счет этих вещей сам язык во многом гораздо лучше, чем другие языки. Например union types, intersection types, enumerated types, более мощные generics, модульность, herd, аннотации и метамодель, кортежи, for comprehensions. Что реально меняет подход к программированию, позволяет писать гораздо более надежный, понятный и универсальный код. Но об этом в следующей части.


Share post

Similar posts

Comments 150

    +15
    :)

      0
      Лучшая статья по Ceylon за последние 3 года. Сам использую и всем рекомендую. Надеюсь, что язык будет и дальше развиваться.
        +5

        Основаная проблема Ceylon — нет вакансий.

          0
          Тот, кто освоил все премудрости Ceylon сможет писать на чем угодно.
            0
            Одна вакансия в Питере точно есть :). А во вторых, на Java тоже нет вакансий ;). Ибо вакансия идет на определенную предметную область под определенные задачи, язык дело десятое. Если умеешь программировать нормально на любом языке и обладаешь навыками в предметной области — без проблем перейдешь.
              +2

              Ребят, я не говорю, что боюсь изучать новую платформу или язык. Я говорю о том, что эти знания несильно востребованы на рынке. По опыту, весьма часто требования диктует не разработчик (особенно новый, особенно, в моём случае, джун-мидл, поскольку не занимаюсь, увы, JVM или компиляцией экзотики в JS), а заказчик или команда. Такие дела.

                0
                Относительно востребованности на рынке. Если у человека в резюме стоит экзотический язык, например Common Lisp — с вероятностью процентов 90 это весьма приличный разработчик. И чем более это экзотический язык, тем интереснее такой кандидат для тех, кто ищет разработчиков, а не желающих просто кодировать всякие CRUD для базы. Однозначно есть люди, которые это понимают. Я, например, один раз даже на Ceylon делал тестовое задание для конторы, которая пишет на Java и Kotlin. Реально произвело фурор :).
                  +1
                  Если у человека в резюме стоит экзотический язык, например Common Lisp — с вероятностью процентов 90 это весьма приличный разработчик.

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

                    0

                    Что то я не встречал студентов-математиков со знанием Лиспа :). Я лучше не буду про преподавание ИТ специальностей в ВУЗах, ибо будут непечатные слова. Так скажем, типичный выпускник прикладной математики в лучшем случае в настоящее время паскаль знает.
                    Обычно изучается это все самостоятельно, SICP и тому подобное. Но я реально знаю двух людей с 4-мя годами коммерческого опыта на Common Lisp.

                      –1
                      Сейчас учат Python
                      0
                      Либо ему просто стало скучно 90% рабочего времени тратить на ковыряние в памяти, указателях и интерфейсах, и он решил выйти на 80-ый уровень искусства программирования.
                      +1
                      Вообще тут надо спросить человека, зачем он этот экзотический язык выбрал, и какие задачи на нем решал. А то могут быть варианты…
                  0
                  Знаете, за последние лет 10 наверное, я ни разу не встречал такого проекта, где бы я не мог обосновать руководству или заказчику, что надо писать на таком-то инструменте.

                  Т.е. было такое, когда заказчик скажем говорит — у нас куплены Oracle и Weblogic, делаем на них (версии такие-то). Но при этом спокойно можно было параллельно брать любой другой инструмент, который повышает вашу производительность или качество кода. Вменяемый заказчик — только за такое.

                  Сейчас вот на моем бывшем проекте, откуда я ушел, пытаются переписывать на котлин. Я бы этого не стал делать (не потому что язык плох, а скорее потому, что основные проблемы лежат не в той в плоскости, чтобы их решал другой язык разработки), но опять же — заказчику все равно, ты разработчик — ты и выбирай инструмент. Если он бесплатен и хоть более-менее распространен — как правило всем кроме вас это до лампочки.
                    –1
                    Основаная проблема Ceylon — нет вакансий.


                    Эта основная проблема только для кодеров.

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

                    0
                    Простите за профанский вопрос, я к вам из JS…
                    Почему в пункте 5 при "===" получаем false?
                      +1
                      === сравнивает значения указателей. То есть обычное == в Java. А == Ceylon отображается на .equals в Java.
                        0

                        С этими равенствами, кстати, я уже в Котлине обжёгся.


                        if(type === TYPE_VARIABLE || type === TYPE_PARAMETER || type == TYPE_FUNCTION || 
                           type === TYPE_METHOD || type === TYPE_FIELD) { ... }

                        Заметили опечатку? В джаве такая опечатка невозможна, а в Котлине/Цейлоне — легко (и я их видел в реальном коде).

                          0

                          Опечатку то я заметил.
                          Ну, в Ceylon я б такое написал как:


                          if (type in {typeVariable,typeParameter,typeFunction,typeMethod,typeField}) {...}

                          И вообще то, за все время написания на ceylon мне ни разу не приходилось использовать === оператор. Я даже забыл что он есть :).

                            +1

                            Разумеется, вы заметили опечатку, перед вами же две строчки кода, а не проект из тысячи файлов, в одном из которых опечатка. Зачем же был введён ненужный оператор? :-) В дизайне языка самое главное — не решить, что в него добавлять, а решить, что в него добавлять не стоит. С этим, кстати, очень большая проблема у груви (@RockPresident привет). Грувисты всегда хвастаются тем, что у них есть, но не могут похвастаться тем, чего у них нету. Котлин гораздо лучше именно потому, что в нём меньше фич. И то несмотря на юный возраст Котлина, в нём уже есть лишние вещи.

                        +1
                        Там же сказано, что сравниваются ссылки. Это два разных объекта в памяти.
                        upd: немного опоздал.
                          +1
                          Кстати, т.к. Ceylon компилируется в JS его можно трактовать как очень мощно типизированный JavaScript.
                            0
                            Даже более того. Для JavaScript у Ceylon есть функционал Type Functions, в результате там с типами становится даже поинтереснее, чем на Java :).
                            0
                            Понял, спасибо!
                          +2
                          А вот у меня вопросец. Я про этот яп узнал просто потому, что случайно набрел на него в сети. А почему он не выстрелил то? Он настолько страшный, что в него народ не пошел? Ей богу даже smalltalk чаще всплывает в инфополе чем этот яп.
                            0
                            Язык новый. На сам язык брошены ресурсы гораздо меньшие, чем на Kotlin. Раз так в 20 точно меньшие. Scala тоже очень долго не взлетала, а сейчас чуть ли не мейнстрим. В принципе только с начала этого года на Ceylon стало удовлетворительно писать используя IDEA. Eclipse ИМХО сильно на любителя. Посмотрим, может и выстрелить через определенное количество времени.
                              +1

                              Вероятно, Red Hat не пиарят его так, как это делаю JetBrains, Google, Mozilla и Apple свои языки

                              +2
                              Аналог implicit там есть? В связи с развитием методологии Type Driven Development это важная фича.
                              Вообще что в нем есть, чего нет в Scala?
                              А вот необходимость писать return после Scala отпугивает.
                                0
                                implicit нет. Сознательно не стали делать, как и в Kotlin, чтобы не усложнять язык. В Kotlin и Ceylon есть хорошее решение проблем Null Safety. В результате чего нет необходимости использовать монады и усложнять код там, где можно без этого обойтись. Также в Ceylon гораздо лучшая система типов чем в практически любом языке, очень интересная типобезопасная рефлексия. Очень хорошие for comprehensions, практически как в Python и гораздо более читабельные, чем в scala. Очень хорошая поддержка Typles. И т.д, о чем отдельно. Собственно это первая часть статьи, где Ceylon выступал на поле Kotlin и оценивался по критериям Kotlin. Далее попробуем повоевать на поле Ceylon :)
                                  +3
                                  По мне так использование монад для Option удобно и позволяет писать общий код для разных контейнеров.
                                  А for в Ceylon c монадами работает (Future и тп)?
                                    0

                                    При необходимости можно использовать такие же приемы, как на Java 8 и Scala. Например вся асинхронность к меня завернута в rxJava. И далее всякие композиции, map, flatmap и и.д. Хотя, если честно, предпочел бы async await функциональность, которой пока нет — это ИМХО более читаемо.


                                    Если имеется в виду код:


                                    for {
                                       r1 <- future1
                                       r2 <- future2
                                       r3 <- future3
                                    } yield (r1+r2+r3)

                                    То на ceylon он бы выглядел как:


                                    value r = {
                                        for (r1 in future1)
                                        for (r2 in future2)
                                        for (r3 in future3)
                                        r1 + r2 + r3
                                    }

                                    Естественно это все нужно предварительно заврапить

                                      0
                                      Я попробовал «async await», реализованный библиотекой в Scala и нашел эту функциональность ужасной, особенно когда пытаешся писать достаточно обобщенный код или работать со списками ассинхронных операций.
                                      for в Ceylon получает блок? Я могу написать аналог
                                      for {
                                       r1 <- future1
                                       r2 = r1+1
                                       r3 <- future3
                                      } yield {
                                       r2/r3
                                      }
                                      
                                        +1

                                        На ceylon это будет примерно так:


                                        value r = {
                                            for (r1 in future1)
                                            let(r2 = r1 + 1)
                                            for (r3 in future3)
                                            r2 / r3
                                        }

                                        На деле это обычный for. Future в данном случае должна быть просто Iterable, просто возвращая одно значение. Для каждой итерации будет выполнен код, который идет после for. И далее это все обернется в ленивый Iterable. Если нужно не лениво, то вместо {for ...} будет [for ...] или можно {for ...}.sequence

                                          +1
                                          Хорошо.
                                          Только скобки в for и let смущают, как-то не ожидаешь, что описаные величины внутри скобок будут доступны в объемлющем блоке. С таким с только в макросах сталкивался.
                                            0

                                            На самом деле для такой задачи можно обычным map и flatMap обойтись, без всяких for, читаемость будет по крайней мере на ceylon больше. for comprehensions не совсем для этого нужен. Но если очень хочется — почему нет :)?

                                  0
                                  Кстати, в принципе можно обойтись и без return. Если мы пишем в функциональной парадигме, то можно воспользоваться => оператором вместо {}, в этом случае return не нужен. Во многих случаях это несколько ухудшает читаемость кода, приходится пользоваться оператором let и тому подобное, но возможно. В Kotlin кстати примерно такая же ситуация с return, как и в Ceylon.
                                    0
                                    Собственно, одна из причин, почему Kotlin меня отталкивает.
                                    +1

                                    А зачем implicit нужен, кстати?


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

                                      +1
                                      Полного аналога на haskell скорее всего нет. Но, в частности, type class из haskell и trait из rust в scala — частный случай использования implicit.
                                      В частности в котлине не написать метод, аналогичный mempty из haskell, Monoid[T].empty из scala и Default::default() из rust.
                                        0

                                        А в скале, оказывается, два implicit'а, implicit params и implicit classes. Речь идёт о втором, я так понимаю?

                                          +1
                                          Они связаны, но речь о первом. С точки зрения scala реализация для типа `T` type class `Monoid` — это требование наличия в текущем контексте implicit объекта/метода типа `Monoid[T]`. Отсюда, кстати, необычный для haskell эффект: в одной кодовой базе может быть 2 реализации одного type class, например если вам требуется 2 разных маршалинга в JSON для ваших типов (1 в БД, другой — в REST), вы можете написать/получить макросами 2 реализации `Format[T]` и в месте использования импортировать нужную. Отсюда же не очевидное неудобство, от которого сейчас избавляются в Dotty.

                                          На самом деле «implicit classes» — это частный случай к implicit conversion. И по сути это ближе всего к extension methods, но с тем важным отличием, что возможно не только добавление отдельных методов, но и приведение к интерфейсам.

                                          Хотите подробней — я ниже ссылку кинул — лучше Одерски я не расскажу, но могу ответить на конкретные вопросы, если возникнут.
                                            +2

                                            Интересный подход к реализации этаких тайпклассов. Интересно, правда, зачем сделано именно так, но, видимо, действительно лучше посмотреть видео, спасибо.


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

                                        0

                                        Как минимум это полезно при написании DSL. На Scala можно написать очень навороченные DSL практически любого синтаксиса. В этой области Scala рулит и рулит просто неимоверно. На Kotlin возможностей по написанию DSL будет поменьше, некоторых вещей будет не хватать. На Ceylon ситуация хуже, чем у Kotlin. За счет обязательной точки с запятой и из за того, что вызов функции всегда идет с указанием скобочек, и нельзя аргументы передавать через пробел. Но намного намного лучше, чем на Java.


                                        Но вообще, 3 языка вполне имеют право на жизнь в настоящее время, у каждого из языков есть свои сильные и слабые стороны. Ни Scala, ни Kotlin, ни Ceylon, не являются серебряной пулей, подходящей ко всем задачам.

                                          0
                                          Но если хотите объяснения что такое implicit, то лучше послушать Одерски: What to Leave Implicit. Только учтите, что все такие доклады больше рассчитаны на людей из java, а не из haskrll.
                                        +1
                                        Вопрос по пункту 8, если я правильно помню то фишка switch в том что строится таблица с адресами переходов и за счет этого код выполняется эффективно. А с такими конструкциями
                                        case(is String)
                                        
                                        не превращается ли switch просто в более красивую запись дерева условий?
                                          +2

                                          Со switch там интереснее. Как это под капотом, по существу не важно, это 100 раз могут безболезненно поменять


                                          У switch там совсем другое назначение по сравнению c Java. Именно в Java я его практически не использую, кстати, ибо вероятность что я там ошибусь и поставлю break достаточно высока.


                                          Предположим у меня тип


                                          Integer|Exception i = Integer.parse("56);

                                          Или же что поинтереснее:


                                          Integer|Exception|Complex p = doComplexParsing("345|45");

                                          Если я делаю switch(p)
                                          То сама IDE заставит меня и сгенерирует код для обработки всех возможных вариантов p
                                          То есть


                                          case(is Integer) {}
                                          case(is Exception) {}
                                          case(is Complex) {}

                                          И если какого case не будет или не будет else, то ругнется компилятор, что я не все возможные значения отработал. За счет чего использование switch в Ceylon очень даже приветствуется.


                                          Ну и также когда switch используется совместно с tuple, entry и деструктуризацией — получается весьма неплохой код, почти паттерн матчинг.

                                            +1
                                            Если я правильно понял, там полноценный pattern matching.
                                            Ну и то, что это выражение, а не оператор, удобно.
                                              +1

                                              К сожалению нет.


                                              Для полноценного хотелось бы:


                                              case(Person("Vasja", 33)) { print("this is Vasja 33")} //не поддерживается
                                              case(Animal(name)) {print(name);} //не поддерживается
                                              case(["56", a]) {print(a)}; //не поддерживается,придется делать case([String str, Object a]) {if (str == "56") {print(a)}};
                                                +2
                                                Странно. Как без этого можно жить?
                                                  +1

                                                  Жить можно без чего угодно. На Java нет даже близко ничего подобного, и народ как то не жалуется. Ибо про альтернативы не знает. Частые use case язык покрывает, остальное возможно появится в будущем. На практике очень часто используются кортежи и их деструктуризация, соответственно для значительной части задач этого хватает.

                                                    +2
                                                    С современной поддержкой IDE удобно заводить case class/data class на каждый чих. Кортежи как-то снижают преимущество от статической типизации.
                                                      0

                                                      Если бы были эти case class/data class. Но вообще, обещают алиасы класса на кортеж, но скорее всего будет не в этом релизе. Соответственно будет достаточно статически типизованно. Будет почти data class.
                                                      Надо понимать, что Ceylon это не Scala и не Kotlin. У него свои бест практики.

                                                      0
                                                      Насчет близко — это вопрос немного субъективный. Вы javaslang видели?
                                                        0

                                                        Так это же библиотеки, а не сам язык. За счет библиотек можно сделать ОЧЕНЬ многое на любом языке. Вот только библиотеки — это не забыть добавить зависимости, не забыть про статик импорты, выглядит это чужеродно, большинство разработчиков про такое не знают ибо не всегда распространено, в конкретной конторе такую библиотеку могут вообще запретить к применению ибо каждую внешнюю либу нужно согласовывать в 10 инстанциях и т.д. Нужно следить за версиями библиотек и их зависимостями и тому подобное. Можно все, на любом языке. Хотя бы кодогенерацией :). Вопрос в лишних телодвижениях. В свое время я делал эти телодвижения и считал, что Java прекрасна ибо на ней можно все. А потом попробовал альтернативы, когда много полезного уже есть из коробки. И обратно то уже не хочется ...

                                                          0
                                                          Я прекрасно понимаю, что это библиотека. Я в общем-то просто прокомментировал вот эту фразу:

                                                          >На Java нет даже близко ничего подобного

                                                          Это все-таки не совсем верно. Есть многое, хотя и не совсем таким же образом реализованное. Тот же ломбок, к примеру.

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

                                                          Т.е. мысль-то моя простая — если язык позволяет сделать библиотекой то, что в другом языке требует изменений компилятора — это хороший, годный язык. Ну, типа лиспа :)
                                                            0

                                                            Когда не было лямбд, любители функциональщины прекрасно жили через анонимные классы :). И IDEA даже сворачивала эту громоздкость и код читался практически так же, как в случае с лямбдами :). А когда вышла восьмерка, тот код средствами той же IDEA стало возможным по хинту преобразовать в код с лямбдами, при этом практически ничего и переписывать не приходилось и все продолжило выглядеть так же, как и выглядело.


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

                                                              0
                                                              Я вполне себе помню и применял functionaljava, guava (и еще пару аналогов). Но эстетически это порой было ужасно, а не прекрасно.

                                                              Ну и все-таки, размеры кода сильно сократились в итоге, что позволило его быстрее писать и легче читать.
                                                                0

                                                                Ага, можно ещё Advanced Code Folding поставить, вообще другой язык будет :-)

                                                    • UFO just landed and posted this here
                                                        +1
                                                        Вот 33 — это у нас что?

                                                        Это int, также как в Java 33 это int а не long, short, byte, float, double
                                                        • UFO just landed and posted this here
                                                            +1

                                                            Не антипаттерн это (в общем случае). Посмотрите, как оно в хаскеле и товарищах сделано, никакой каши правил, все ясно и понятно, даже если всякими view patterns и pattern synonyms обмазываться.

                                                            • UFO just landed and posted this here
                                                              0
                                                              от в данном случае Person(«Vasja», 33)

                                                              Должен быть конструктор который принимает String и int.

                                                              call("Vasja", 33)
                                                              

                                                              Откуда вы знаете какой метод будет вызван? Который принимает массив char'ов? Объект с toString()? StringBuilder/StringBuffer? Своя кастомная коллекция с char'ами?
                                                              • UFO just landed and posted this here
                                                                  0
                                                                  поэтому оверлоадинг — отстой

                                                                  Т.е. вы называете методы callStringAndInt?
                                                                    0

                                                                    На самом деле без оверлоадинга в Ceylon можно жить достаточно комфортно. Во первых, оверлоадинг при необходимости делается через Union Types. Метод один, он принимает определенные аргументы, а аргумент может быть или одного типа, или другого. А далее в обработчике либо сразу учитывать логику, либо уже делегировать специфичным непубличным методам. Во вторых, в Java большинство оверлоадинг методов нужны, так как там нет параметров по умолчанию. В третьих, если уж ну совсем приспичило с оверлоадингом, что ну никак не исхитриться (мне не доводилось с таким сталкиваться, но мало ли), то никто не запрещает написать нужную логику на Java, и вызывать этот оверлоадинг из Ceylon.

                                                                      0
                                                                      оверлоадинг при необходимости делается через Union Types

                                                                      Т.е. вместо того чтобы в compile-time знать какой метод надо вызывать, мы теперь будем в run-time определять?
                                                                      Во вторых, в Java большинство оверлоадинг методов нужны, так как там нет параметров по умолчанию.

                                                                      Так ведь тогда и конструктор будет один и не будет неоднозначностей
                                                                        0

                                                                        Да, в рантайме. Да, перфоманс. Но про перфоманс я уже ответил.


                                                                        По поводу оверлоадинга — любопытная статья относительно того, что функционал оверлоадинга весьма затруднил появление в Java лямбд из за чего было множество сложностей и багов.


                                                                        https://objectteams.wordpress.com/2017/04/02/several-languages-java-8/

                                                                    • UFO just landed and posted this here
                                                                        0
                                                                        Ну так и конструктор можно
                                                                        пользуюсь там, где это не вредно и к месту. и проектирую апи так, чтоб не ломались внезапно из-за оверлоадинга.

                                                                        и у вас обычно будет только один конструктор, так что неоднозначностей не будет
                                                                        • UFO just landed and posted this here
                                                                  0
                                                                  Плюс все радости оверлоадинга, когда код может внезапно без палева начать работать по-другому, потому что ты определил более специфичный метод/конструктор.

                                                                  Вы пишите тесты? И как часто вы определяете более специфичный метод/конструктор?
                                                                  • UFO just landed and posted this here
                                                                      0
                                                                      А это тут при чем?

                                                                      образовалось: 95% написанного кода работают сразу, как удовлетворил компилятор еще до запуска

                                                                      Потому что не 100%. Вы все ровно пишите тесты и можете проверить какой метод вызвался. А с паттерн матчингом еще и код более читабельный.
                                                                      • UFO just landed and posted this here
                                                                          +3
                                                                          Вы все ровно пишите тесты и можете проверить какой метод вызвался.

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


                                                                          95% вместо 100% потому, что есть логические ошибки, связанные тупо с неправильно построенным алгоритмом.

                                                                            0
                                                                            Как тайпчекер и свойства языка могут гарантировать что например вызвался метод отправвки эмейла при регистрации?
                                                                              0

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

                                                                                0
                                                                                Не проше ли это тестом проверить?
                                                                                  0

                                                                                  _

                                                                                    +1

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

                                                                                      0
                                                                                      Использовать типизацию проше чем писать тесты.
                                                                                      Писать тесты проше чем " линейными типами и единственностью реализации какого-нибудь тайпкласса для типа, описывающего процесс регистрации"
                                                                                        0
                                                                                        Использовать типизацию проше чем писать тесты.

                                                                                        Сторонники динамической типизации будут спорить. (:


                                                                                        Писать тесты проше чем " линейными типами и единственностью реализации какого-нибудь тайпкласса для типа, описывающего процесс регистрации"

                                                                                        Зависит от того насколько удобно это реализовано в языке.

                                                                                          0

                                                                                          Независимо от того, насколько удобно это сделано, такая проверка является неправильной.


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

                                                                                            0

                                                                                            Ну так статическим тестом и является типизация, а тайпчекер выполняет роль запускалки этих тестов.

                                                                                          0

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

                                                              +4
                                                              Интерполяция строк
                                                              Это как бы более умная и читабельная версия String.format() из Java, встроенная в язык:
                                                              value x = 4;
                                                              value y = 7;
                                                              print("sum of ``x`` and ``y`` is ``x + y``"); // sum of 4 and 7 is 11
                                                              


                                                              ИМХО синтаксис здесь будет поприятнее, чем в Kotlin, с Java даже не хочется сравнивать.

                                                              Kotlin
                                                              val x = 4
                                                              val y = 7
                                                              print("sum of $x and $y is ${x + y}") // sum of 4 and 7 is 11
                                                              

                                                              и что вам тут не нравиться?
                                                                0

                                                                Знак ${}.
                                                                Приведу цитату из FAQ непосредственно от разработчиков языка https://ceylon-lang.org/documentation/1.3/faq/language-design/#string_interpolation_syntax:


                                                                Why not "Hello $name" or "Hello ${name.uppercased}"?

                                                                Primarily because it looks a bit cleaner for defining text in user interfaces or other treelike structures.


                                                                Html hello {
                                                                    Head head { title="Greeting"; }
                                                                    Body body {
                                                                        P { "Hello ``name``. Welcome back!" }
                                                                    }
                                                                }

                                                                We did originally investigate the ${...} syntax, but it turns out that syntax would require a stateful lexer and, since } is a legal token in the language, is more fragile when editing code in an IDE. Anyway, some of us just don't love seeing dollar signs all over the place. It reminds us of languages we don't like.

                                                                  +1
                                                                  Anyway, some of us just don't love seeing dollar signs all over the place. It reminds us of languages we don't like.

                                                                  Т.е. не нравится Java, но синтаксис уноследовали, а знак доллара не нравится, его не взяли.
                                                                    0

                                                                    Синтаксис Java унаследован частично. Например не public, а shared, не implements а satisfies и т.д. Из Java в основном идет имя типа слева от переменной, ключевой слово class и фигурные скобочки. Сам язык просто создавался с нуля, с учетом того хорошего, что было до этого.

                                                                    • UFO just landed and posted this here
                                                                      +2
                                                                      Вопрос спорный. И явно личные предпочтения тут перевесили.

                                                                      P.S. Мне тоже `` напоминает кое-что из того, что хотелось бы забыть.
                                                                        0

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

                                                                          0
                                                                          Чем это лучше?
                                                                            +1
                                                                            1. Упрощает ядро языка.
                                                                            2. Позволяет реализовать разные варианты, хоть с долларами, хоть с #{expr}, хоть с backtick'ами.
                                                                            3. Позволяет реализовывать всякие другие нереализованные в ядре языка вещи, вроде типобезопасного printf с проверкой строки формата в компил-тайме.
                                                                            4. Даёт чуть большую уверенность, что язык в известном смысле правильно спроектирован, если в нём такие вещи выражаются достаточно просто.
                                                                              –1
                                                                              Позволяет реализовать разные варианты, хоть с долларами, хоть с #{expr}, хоть с backtick'ами.

                                                                              Это скорее минус, если каждый будет делать как он хочет.

                                                                              Самое часто используемое должно быть по умолчанию. Интерполяция и есть самое часто используемое в строках.
                                                                      +2
                                                                      Хочу рассказать о новом языке программирования, который называется Ceylon

                                                                      Kotlin не вчера появился, но Ceylon по моему, старше Kotlin-а лет так на 5 или 6, у него первый стабильный релиз был в 2011, когда Kotlin только только зарождался.

                                                                        0
                                                                        Котлин до 1й стабильной версии шел долго. А у цейлона поддержки в идее не было.
                                                                        0
                                                                        В отличие от Kotlin обошлось без ключевого слова downTo.

                                                                        value n = 10;
                                                                        value m = 2;
                                                                        
                                                                        for (i in n..m) { ... }  
                                                                        

                                                                        Ceylon в рантайме делает проверки?
                                                                          0

                                                                          n..m это просто синтаксический сахар для Range.


                                                                          Внутри код вроде:


                                                                              shared actual 
                                                                              Element[] span(Integer from, Integer to) {
                                                                                  if (from <= to) {
                                                                            0
                                                                            if (from <= to) {

                                                                            Т.е. каждый раз проверяется в рантайме :(

                                                                            А если нам надо чтобы цикл выполнялся только если n < m?
                                                                              0

                                                                              На выбор:


                                                                              for(n in 0..m) {...}
                                                                              for(n in minInteger..m) {...}
                                                                              for(n in spanTo(m)) {...}
                                                                                0
                                                                                Эээ, у меня функция принимает n и m
                                                                                void count(Integer n, Integer m) {
                                                                                    for (i in n..m) {
                                                                                         print(i);
                                                                                    }
                                                                                }
                                                                                

                                                                                так вот, мне надо чтобы метод print исполнялся только если n < m
                                                                                  0
                                                                                  if (n >= m) { return; } // причем на практике скорее всего будет assert(n<m);
                                                                                  
                                                                                  for (i in n..m) {
                                                                                      print(i);
                                                                                  }
                                                                                    +1
                                                                                    Уж лучше с downTo. Кстати это не ключевое слово.
                                                                          +3

                                                                          И тот и другой 2011. По сравнению со Scala, которая в 2003 появилась. Scala стала мейнстримом где то последние года 4, по крайней мере на scala можно найти работу без проблем. Kotlin стал настолько популярен, что на нем можно найти работу — тоже только в последние несколько лет. Но на Ceylon тоже можно работу найти, у меня получилось, когда я искал работу на Scala или Kotlin :):):).


                                                                          Что считать стабильным релизом на самом деле еще и вопрос. Первая стабильная версия 1.0.0 в 2013 году. В гораздо более стабильном языке я лично зарепортил весьма немало багов, некоторые даже сам и поправил :).

                                                                            +2

                                                                            Читаю все эти статьи и не пропадает впечатление что авторы просто не слышали о языке Groovy? В котором всё это уже есть лет 10, да плюс ещё огромное количество настолько же полезных возможностей. Стабильный язык, почти полная совместимость с .java кодом (и причём не такая где можно использовать другие java библиотеки, а в том смысле что можно просто взять .java файл, и он скомпилируется groovy сразу), полное решение всех verbosity проблем которые есть у джавы, куча паттернов позволяющих быстро прототипировать и вообще писать код, хорошая читаемость, узнаваемость, convention over configuration, свободный выбор между static type compilation/dynamic type compilation, (причём на уровне отдельных классов или даже методов!) и так далее.


                                                                            Автор, если вы не пробовали Groovy, обязательно сделайте это.

                                                                              0
                                                                              Присоединюсь к пожеланиям статьи о преимуществах по сравнению с Groovy, т.к. когда делали Ceylon Groovy уже был и Гэвин Кинг об этом знал. Значит Groovy чем то не устраивал.
                                                                                0
                                                                                NIH синдром как он есть
                                                                                  +1

                                                                                  Ещё была Scala.)

                                                                                  0
                                                                                  Знаете, я в прошлой статье про котлин прокомментировал в том же духе — так мне минусов понаставили. Причем аргументировали один раз — что производительность groovy плохая (а подтвердить при этом ничем не удосужились). А по сути тут вопрос ровно тот же встает — а чем это лучше groovy? Который не просто появился давно, но и распространен весьма широко (как сам по себе, так и в виде gradle например, и не только), и большую часть ровно этих же преимуществ имеет (ну кроме компиляции в JS, пожалуй).
                                                                                    +2
                                                                                    Либо его недостаточно пиарили. Либо я что то пропустил:
                                                                                    1) Как у groovy с иммутабельностью по умолчанию?
                                                                                    2) Как там дела с for comprehensions?
                                                                                    3) как там дела с деструктуризацией кортежей, причем чтоб деструктуризация была прямо в лямбдах?
                                                                                    4) Как там с женериками? Можно ли в groovy у List узнать в рантайме тип T?
                                                                                      0
                                                                                      Вы пропустили gradle? Серьезно? А в остальном — да, это некоторые из реальных недостатков (ну, их можно считать такими).

                                                                                      1. По умолчаню — никак. А вообще примерно как в Java, можно написать аннотацию Immutable, т.е. по сути — на уровне обработки AST где-то достигается. Встроено в язык.
                                                                                      2. В принципе. средства расширения языка (включая и лямбды сюда же) вполне позволяют например написать свой цикл until, имея только лямбды. Не задумывался об этом, но подозреваю, что можно сделать вполне пригодное что-то.
                                                                                      3. Простой запрос гуглю отвечает ссылкой http://groovy-lang.org/semantics.html#_object_destructuring_with_multiple_assignment, которая показывает, что это тоже одна из возможностей расширения языка. Т.е. есть multi assignment, и можно кое-какие методы объекту дописать, чтобы он деструктурировался. Не блестяще наверное, но напомню — этому языку уже лет 10.
                                                                                      4. По-моему также, как в Java. Тип T можно узнать, он сохраняется в байткоде, но скажем так — не слишком прямолинейно это делается. Я подозреваю, большинство программистов про этот способ не слышали. TypeToken например погуглите, это из guava. Type erasure тут сильно мешает, и язык мало что может с этим сделать (разве что нарушив совместимость с Java на уровне байткода, что мы видим на примере скалы).
                                                                                    +1

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

                                                                                    +1
                                                                                    Обожаю Groovy! По-моему, недооцененный язык.

                                                                                    Но всё-таки хочется уточнить:
                                                                                    можно просто взять .java файл, и он скомпилируется groovy сразу

                                                                                    Это true только для java-файла до 1.7 включительно. Лямбды из 1.8, например, не скомпилируются.
                                                                                      0
                                                                                      Да. Поддержка 1.8 вроде ожидается. Когда будет — непонятно.
                                                                                    0
                                                                                    С нетерпением жду подобную статью про Groovy, Jython и т.п. :)
                                                                                      0
                                                                                      С Jython все не так красиво. Насколько я понимаю, язык застрял на уровне версии 2.x. И версии 3.x похоже не будет никогда.
                                                                                        0
                                                                                        Да, но и сам Python 2 ещё вполне востребован и похоже будет востребован ещё долго.
                                                                                          0
                                                                                          Ну, если вас 2 устраивает, то версия 2.7 есть, в этом плане все более-менее хорошо. А с учетом того, что доступна вся инфраструктура Java, я бы даже сказал, что очень хорошо. Для некоторых задач. Я когда-то применял внутри Weblogic — и остался более чем доволен.
                                                                                            0

                                                                                            Уже не долго. Срок поддержки заканчивается в 2020 году. Django, ipython больше не поддерживают 2 ветку. В Heroku теперь версия по умолчанию — 3.6

                                                                                      • UFO just landed and posted this here
                                                                                          0

                                                                                          Что вы имеете ввиду? Насколько мне известно любой Java код можно вызвать из Scala, наоборот нет и это очевидно.) Scala более богатый на возможности язык чем Java.

                                                                                            –1

                                                                                            Наоборот тоже прекрасно вызывается. Через одно место, громоздко, криво, но вызывается :).

                                                                                            • UFO just landed and posted this here
                                                                                                +1

                                                                                                Наоборот нет? Я помнится извращался, и вызывал Scala код не только из Java, но и из Ceylon.

                                                                                                  0
                                                                                                  Это возможно в очень многих случаях, но есть исключения. Самое явное — макросы.
                                                                                                0
                                                                                                И Scala, и, как оказалось, Kotlin не на 100% совместимы с Java, ваши комментарии по этому поводу?

                                                                                                C Java как языком, или с некоторыми Java библиотеками и некоторыми тяжелыми серверами :)? Именно с взаимодействием с Java проблем нет. Как в одну, так и в другую сторону. Например я люблю в IDEA в момент точки останова делать evaluate expression, и вызывать непосредственно нужный метод. Я это любил делать в Java — я продолжаю таким заниматьсяи в Ceylon, хоть и мне приходится знать как ко всему этому достучаться из Java. Возможно с выходом Java 9 на начальном этапе будут какие то мелкие проблемы, а может и крупные, пока нормальной поддержки Java 9 не появится в языке. До версии Ceylon 1.3.0 были мелкие проблемы с взаимодействием с Java 8, но тоже вполне решаемые.


                                                                                                Почему столько вариантов и чем они друг от друга отличаются? (Кроме очевидного by.)

                                                                                                Включая, не включая, в обратном порядке, c шагом, проверка на нахождение в диапазон в if. Там можно и поболее вариантов привести.


                                                                                                И самый главный вопрос, почему же стоит переходить на Ceylon или Kotlin?

                                                                                                Про это будет далее. Если коротко в этих языках исправлены фундаментальные недостатки Java. А именно — многословность, мутабельность по умолчанию, проблема c null safety. Весьма поднимает это все производительность разработки.

                                                                                                • UFO just landed and posted this here
                                                                                                    0
                                                                                                    Это тоже делается. Например через рефлексию. Грубо говоря, достается шаблон типа, он параметризуется нужным типом, и далее инстанцируется. Получается да, громоздко и неудобно, даже на цейлоне это не совсем тривиально. Но если есть такая необходимость — это все делается. На практике же лучше такого высшего пилотажа избегать, и если потребуется чтоб ceylon код вызывать из Java — лучше предоставить там Java API без всяких овеществленных дженериков. Если есть такая возможность, естественно.
                                                                                                    • UFO just landed and posted this here
                                                                                                        0
                                                                                                        А как вы себе 100% совместимость представляете, если в java ее нет?
                                                                                                          +1

                                                                                                          В Kotlin выкинули овеществленные дженерики чтобы со стороны Java код выглядел нормально. Без этой жертвы странно говорит про 100% или даже 99% совместимость с Java.

                                                                                                            0

                                                                                                            Я немного не понимаю какие тут большие проблемы. Вот код использования из Java ceylon ArrayList вместе с цейлоновскими же строками:


                                                                                                            ceylon.collection.ArrayList<ceylon.language.String> ceylonStrArr = new ceylon.collection.ArrayList<ceylon.language.String>(ceylon.language.String.$TypeDescriptor$);
                                                                                                            ceylonStrArr.add(ceylon.language.String.instance("I am adding ceylon string from Java"));

                                                                                                            Специально не убирал явные имена пакетов, из за чего здесь это выглядит громоздко. Все проблема с овеществленными женериками из Java некрасивый $TypeDescriptor$ в конструкторе.

                                                                                                              0

                                                                                                              Единственная практическая проблема с вызовом из Java кода кода на Ceylon заключается в IDE. IDE да, пока не видит из Java цейлоновские классы. Из за чего внутри среды разработки Java код, вызывающий Ceylon код выглядит красным. Но это компилируется и запускается. И эта проблема актуально только в том случае, если проект изначально цейлоновский, и я мешаю там вызовы из Java в Ceylon. Если же цеплять jar, написанный на Ceylon к уже существующему проекту, то таких проблем не будет. Но рано или поздно это пофиксят, соответствующая бага давно заведена.

                                                                                                                +1

                                                                                                                API где нужно всюду передавать $TypeDescriptor$ не назовешь идиоматичным Java кодом.


                                                                                                                Я хотел еще раз подчеркнуть что в Kotlin трактовке "совместимость в обе стороны" подразумевает идиоматичный вид Java из Kotlin и Kotlin из Java. Мне кажется этот очень важный факт принижается в статье с отмашкой "где мы такое не видели".

                                                                                                    0
                                                                                                    Навскидку (с цейлоном у меня даже хуже, чем с котлином): Цейлон позволяет отличить MyClass<Integer> от MyClass<String> в case. Достигается за счет доп. информации в инстансах дженериков. Сломается если MyClass<T> создан в java. Как это взаимодействует с джавовыми либами, создающими экземпляре на основе рефлексии (маршалинг, БД, etc), я затрудняюсь предугадать.
                                                                                                    –1
                                                                                                    я не профи, но какая разница? Ceylon… Kotlin… все конструкции очень похожи друг на друга
                                                                                                    наверное заминусуют сейчас люто, но!
                                                                                                    вы видели современный swift? Там все тоже самое, различия минимальны
                                                                                                      0
                                                                                                      Ceylon, Kotlin, Scala — это JVM языки. JVM инфраструктура реально огромна, уже для Java написано огромное количество прекрасных библиотек и фреймворков. На Ceylon я могу, например, взять HazelCast, и писать линейно масштабируемое облачное распределенное ПО. Получив распределенные лямбды, распределенные локи, распределенные кеши, распределенные экзекуторы и т.д. И я не просто могу теоретически, я это делал практически. Продолжить писать код, выглядящий как работающий на одной машине, но де факто исполняющийся на кластере из тысячи серверов. Я могу взять vertx, и получить распределенный асинхронный фреймворк, который без проблем кластеризуется и требует минимум настройки. Я могу взять akka, и писать в парадигме акторов, не бояться дедлоков и вообще думать не о потоках, а о бизнес логике. Я могу взять rxJava, reacive streams, и работать с асинхронным кодом практически как с синхронным. Java инфраструктура очень хороша для бекнда и серверной разработки. Kotlin сейчас весьма популярен во фронтэнде за счет поддержки Android. Ceylon в принципе для этого тоже можно использовать, но мои задачи от фронтэнда далеко, потому насколько он хорош, я сказать не могу. Можете кстати посмотреть недавное выступление Gavin King где он рассказывает как он переписывал тестовый Android проект с Java на Ceylon. https://www.youtube.com/watch?v=zBtSimUYALU
                                                                                                      +2
                                                                                                      Популярность вакансий у нас, относительно Java:
                                                                                                      Scala — 11%
                                                                                                      Groovy — 7.4% (тестировщики :)
                                                                                                      Kotlin — 1.7% — просто Java с доп. требованиями Котлина.
                                                                                                      Ceylon — 0
                                                                                                      • UFO just landed and posted this here
                                                                                                          0
                                                                                                          Ceylon не 0. А в настоящее время минимум 1 вакансия, а то и вообще 3. В вакансии только нет ни слова про Ceylon, там Java стоит, кандидатов шокируют позднее :). Актуально для Питера, деньги не суперские, но и не совсем доширак, если кому интересно — можно в личку стучаться.
                                                                                                        • UFO just landed and posted this here
                                                                                                            0
                                                                                                            Эх, не хватает async/await.
                                                                                                              0

                                                                                                              Как работают стандартные коллекции в Ceylon? Они "свои" или используются классы из JDK? Если я использую совместимость с Java, придется ли мне копировать (даже если и неявно) из коллекции в коллекцию?

                                                                                                                0
                                                                                                                Коллекции свои, написанные с нуля. Если совмещать Java и Ceylon коллекции — да, придется копировать. Синтаксис работы с Java коллекциями достаточно прозрачный и в принципе с Java коллекциями можно довольно комфортно работать. В основном на практике использую Java коллекции, когда мне нужно parallelStream использовать или если использую Java библиотеку. По умолчанию чаще всего стараюсь использовать не List, а Sequence или Iterable, а коллекции только когда реально необходимо. Ибо синтаксис Sequence и Iterable ИМХО гораздо чище. Если коллекции реально нужны, приоритет отдаю цейлоновским, если нельзя (например мне нужны коллекции из пакета Concurrent, а у цейлона на уровне языка поддержки многопоточности нет вообще) — используем Java коллекции. Один разок я даже Scala коллекции решил заюзать, завелось без проблем.
                                                                                                                  0

                                                                                                                  Звучит так как будто при неосторожном смешивании библиотек производительность начинает резко просидать. Так себе ситуация, IMHO. Подход Kotlin с черной магией в компиляторе в этом смысле сильно лучше.


                                                                                                                  Я понимаю что в этой статье вы не ставили себе задачу сравнить все за и против, но вообще это был бы один из минусов Ceylon.

                                                                                                                    +1

                                                                                                                    На самом деле, когда реально важна производительность, там вообще не до коллекций :). Уже и на Java узким местом становится боксинг анбоксинг и тому подобные приколы, потому может потребоваться отказаться от Java коллекций в сторону обычных массивов примитивов. Как в одном из наших проектов на Ceylon, на каждый уникальный запрос перелопачивали в памяти 500 миллионов записей с фильтрацией группировкой аггрегацией на кластере :). Пришлось посидеть с профайлером и ускорить удалось где то в 60 раз. Узкие места были переписаны на Java. Но именно взаимодействие Java кода с Ceylon кодом для наших задач никогда не была узким местом. В настоящее время узкое место — скорость DoubleAccumulator. Предполагаю можно еще процентов на 30 поднять, и возможно еще раза в 2-3, если использовать кодогенерацию в Java и использование JavaCompilerAPI ради разворачивания циклов, но уже скорости хватает. И так практически в шину памяти удалось упереться, за 3 секунды перелопатить 30 гигов на каждой ноде это не так чтобы и медленно. Если бы проект писался целиком на Java, а не на Ceylon — быстрее бы точно не было. А так, переписать на Java пришлось процентов 10 кода. После профилирования. И даже если б писалось это изначально на Java — пришлось бы узкие места точно так же переписывать.


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


                                                                                                                    Если уж касаться оптимизаций — некоторые вещи у нас вообще сишные либы делают. Причем этим сишным либам еще и кластер нужен :). Соответственно мы из Ceylon вызываем Java библиотеки, которые являются обертками над сишными библиотеками. И узким местом является именно сишная библиотека. не подготовка данных, а именно тупой расчет.


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

                                                                                                              Only users with full accounts can post comments. Log in, please.