Как стать автором
Обновить

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

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

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

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

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

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

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

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

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

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

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


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

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

НЛО прилетело и опубликовало эту надпись здесь
=== сравнивает значения указателей. То есть обычное == в Java. А == Ceylon отображается на .equals в Java.

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


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

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

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


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

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

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

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

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

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

При необходимости можно использовать такие же приемы, как на 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
}

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

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

На 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

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

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

Кстати, в принципе можно обойтись и без return. Если мы пишем в функциональной парадигме, то можно воспользоваться => оператором вместо {}, в этом случае return не нужен. Во многих случаях это несколько ухудшает читаемость кода, приходится пользоваться оператором let и тому подобное, но возможно. В Kotlin кстати примерно такая же ситуация с return, как и в Ceylon.
Собственно, одна из причин, почему Kotlin меня отталкивает.
НЛО прилетело и опубликовало эту надпись здесь
Полного аналога на haskell скорее всего нет. Но, в частности, type class из haskell и trait из rust в scala — частный случай использования implicit.
В частности в котлине не написать метод, аналогичный mempty из haskell, Monoid[T].empty из scala и Default::default() из rust.
НЛО прилетело и опубликовало эту надпись здесь
Они связаны, но речь о первом. С точки зрения 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, но с тем важным отличием, что возможно не только добавление отдельных методов, но и приведение к интерфейсам.

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

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


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

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

Со 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 и деструктуризацией — получается весьма неплохой код, почти паттерн матчинг.

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

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


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


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)}};
Странно. Как без этого можно жить?

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

НЛО прилетело и опубликовало эту надпись здесь
Вот 33 — это у нас что?

Это int, также как в Java 33 это int а не long, short, byte, float, double
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
от в данном случае Person(«Vasja», 33)

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

call("Vasja", 33)

Откуда вы знаете какой метод будет вызван? Который принимает массив char'ов? Объект с toString()? StringBuilder/StringBuffer? Своя кастомная коллекция с char'ами?
НЛО прилетело и опубликовало эту надпись здесь

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

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

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

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

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


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


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

НЛО прилетело и опубликовало эту надпись здесь
Ну так и конструктор можно
пользуюсь там, где это не вредно и к месту. и проектирую апи так, чтоб не ломались внезапно из-за оверлоадинга.

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

Вы пишите тесты? И как часто вы определяете более специфичный метод/конструктор?
НЛО прилетело и опубликовало эту надпись здесь
А это тут при чем?

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

Потому что не 100%. Вы все ровно пишите тесты и можете проверить какой метод вызвался. А с паттерн матчингом еще и код более читабельный.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Как тайпчекер и свойства языка могут гарантировать что например вызвался метод отправвки эмейла при регистрации?
НЛО прилетело и опубликовало эту надпись здесь
Не проше ли это тестом проверить?

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

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

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


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

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

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


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

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Интерполяция строк
Это как бы более умная и читабельная версия 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

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

Знак ${}.
Приведу цитату из 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.

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, но синтаксис уноследовали, а знак доллара не нравится, его не взяли.

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

НЛО прилетело и опубликовало эту надпись здесь
Вопрос спорный. И явно личные предпочтения тут перевесили.

P.S. Мне тоже `` напоминает кое-что из того, что хотелось бы забыть.
НЛО прилетело и опубликовало эту надпись здесь
Чем это лучше?
НЛО прилетело и опубликовало эту надпись здесь
Позволяет реализовать разные варианты, хоть с долларами, хоть с #{expr}, хоть с backtick'ами.

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

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

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

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

value n = 10;
value m = 2;

for (i in n..m) { ... }  

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

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


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


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

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

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

На выбор:


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

так вот, мне надо чтобы метод print исполнялся только если n < m
if (n >= m) { return; } // причем на практике скорее всего будет assert(n<m);

for (i in n..m) {
    print(i);
}
Уж лучше с downTo. Кстати это не ключевое слово.

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


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

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


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

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

Ещё была Scala.)

Знаете, я в прошлой статье про котлин прокомментировал в том же духе — так мне минусов понаставили. Причем аргументировали один раз — что производительность groovy плохая (а подтвердить при этом ничем не удосужились). А по сути тут вопрос ровно тот же встает — а чем это лучше groovy? Который не просто появился давно, но и распространен весьма широко (как сам по себе, так и в виде gradle например, и не только), и большую часть ровно этих же преимуществ имеет (ну кроме компиляции в JS, пожалуй).
Либо его недостаточно пиарили. Либо я что то пропустил:
1) Как у groovy с иммутабельностью по умолчанию?
2) Как там дела с for comprehensions?
3) как там дела с деструктуризацией кортежей, причем чтоб деструктуризация была прямо в лямбдах?
4) Как там с женериками? Можно ли в groovy у List узнать в рантайме тип T?
Вы пропустили 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 на уровне байткода, что мы видим на примере скалы).
Я когда писал «встроено в язык» именно это и имел в виду — аннотация уже есть, ее логику делать не нужно.

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

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

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

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

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

НЛО прилетело и опубликовало эту надпись здесь

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

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

НЛО прилетело и опубликовало эту надпись здесь

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

Это возможно в очень многих случаях, но есть исключения. Самое явное — макросы.
И 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. Весьма поднимает это все производительность разработки.

НЛО прилетело и опубликовало эту надпись здесь
Это тоже делается. Например через рефлексию. Грубо говоря, достается шаблон типа, он параметризуется нужным типом, и далее инстанцируется. Получается да, громоздко и неудобно, даже на цейлоне это не совсем тривиально. Но если есть такая необходимость — это все делается. На практике же лучше такого высшего пилотажа избегать, и если потребуется чтоб ceylon код вызывать из Java — лучше предоставить там Java API без всяких овеществленных дженериков. Если есть такая возможность, естественно.
НЛО прилетело и опубликовало эту надпись здесь
А как вы себе 100% совместимость представляете, если в java ее нет?

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

Я немного не понимаю какие тут большие проблемы. Вот код использования из 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$ в конструкторе.

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

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


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

Навскидку (с цейлоном у меня даже хуже, чем с котлином): Цейлон позволяет отличить MyClass<Integer> от MyClass<String> в case. Достигается за счет доп. информации в инстансах дженериков. Сломается если MyClass<T> создан в java. Как это взаимодействует с джавовыми либами, создающими экземпляре на основе рефлексии (маршалинг, БД, etc), я затрудняюсь предугадать.
я не профи, но какая разница? Ceylon… Kotlin… все конструкции очень похожи друг на друга
наверное заминусуют сейчас люто, но!
вы видели современный swift? Там все тоже самое, различия минимальны
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
Популярность вакансий у нас, относительно Java:
Scala — 11%
Groovy — 7.4% (тестировщики :)
Kotlin — 1.7% — просто Java с доп. требованиями Котлина.
Ceylon — 0
НЛО прилетело и опубликовало эту надпись здесь
Ceylon не 0. А в настоящее время минимум 1 вакансия, а то и вообще 3. В вакансии только нет ни слова про Ceylon, там Java стоит, кандидатов шокируют позднее :). Актуально для Питера, деньги не суперские, но и не совсем доширак, если кому интересно — можно в личку стучаться.
НЛО прилетело и опубликовало эту надпись здесь
Эх, не хватает async/await.

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

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

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


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

На самом деле, когда реально важна производительность, там вообще не до коллекций :). Уже и на 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 библиотеки, которые являются обертками над сишными библиотеками. И узким местом является именно сишная библиотека. не подготовка данных, а именно тупой расчет.


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

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

Публикации

Истории