В последнее время активную популярность набирает 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. Что реально меняет подход к программированию, позволяет писать гораздо более надежный, понятный и универсальный код. Но об этом в следующей части.
https://ceylon-lang.org/documentation/1.3/introduction/
https://ceylon-lang.org/documentation/1.3/faq/language-design/
https://dzone.com/articles/a-qa-with-gavin-king-on-ceylon
https://www.slant.co/versus/116/390/~scala_vs_ceylon
https://www.slant.co/versus/390/1543/~ceylon_vs_kotlin
https://dzone.com/articles/ceylon-enterprise-ready
http://tryge.com/2013/12/13/ceylon-and-kotlin/
Ockonal
NikNik77771
Лучшая статья по Ceylon за последние 3 года. Сам использую и всем рекомендую. Надеюсь, что язык будет и дальше развиваться.
bohdan4ik
Основаная проблема Ceylon — нет вакансий.
NikNik77771
Тот, кто освоил все премудрости Ceylon сможет писать на чем угодно.
elmal
Одна вакансия в Питере точно есть :). А во вторых, на Java тоже нет вакансий ;). Ибо вакансия идет на определенную предметную область под определенные задачи, язык дело десятое. Если умеешь программировать нормально на любом языке и обладаешь навыками в предметной области — без проблем перейдешь.
bohdan4ik
Ребят, я не говорю, что боюсь изучать новую платформу или язык. Я говорю о том, что эти знания несильно востребованы на рынке. По опыту, весьма часто требования диктует не разработчик (особенно новый, особенно, в моём случае, джун-мидл, поскольку не занимаюсь, увы, JVM или компиляцией экзотики в JS), а заказчик или команда. Такие дела.
elmal
Относительно востребованности на рынке. Если у человека в резюме стоит экзотический язык, например Common Lisp — с вероятностью процентов 90 это весьма приличный разработчик. И чем более это экзотический язык, тем интереснее такой кандидат для тех, кто ищет разработчиков, а не желающих просто кодировать всякие CRUD для базы. Однозначно есть люди, которые это понимают. Я, например, один раз даже на Ceylon делал тестовое задание для конторы, которая пишет на Java и Kotlin. Реально произвело фурор :).
lany
Либо он учился на математическом факультете, где учат только лиспу, умеет доказывать теоремы, но к практическому программированию не готов :-)
elmal
Что то я не встречал студентов-математиков со знанием Лиспа :). Я лучше не буду про преподавание ИТ специальностей в ВУЗах, ибо будут непечатные слова. Так скажем, типичный выпускник прикладной математики в лучшем случае в настоящее время паскаль знает.
Обычно изучается это все самостоятельно, SICP и тому подобное. Но я реально знаю двух людей с 4-мя годами коммерческого опыта на Common Lisp.
mikhanoid
Сейчас учат Python
mikhanoid
Либо ему просто стало скучно 90% рабочего времени тратить на ковыряние в памяти, указателях и интерфейсах, и он решил выйти на 80-ый уровень искусства программирования.
sshikov
Вообще тут надо спросить человека, зачем он этот экзотический язык выбрал, и какие задачи на нем решал. А то могут быть варианты…
sshikov
Знаете, за последние лет 10 наверное, я ни разу не встречал такого проекта, где бы я не мог обосновать руководству или заказчику, что надо писать на таком-то инструменте.
Т.е. было такое, когда заказчик скажем говорит — у нас куплены Oracle и Weblogic, делаем на них (версии такие-то). Но при этом спокойно можно было параллельно брать любой другой инструмент, который повышает вашу производительность или качество кода. Вменяемый заказчик — только за такое.
Сейчас вот на моем бывшем проекте, откуда я ушел, пытаются переписывать на котлин. Я бы этого не стал делать (не потому что язык плох, а скорее потому, что основные проблемы лежат не в той в плоскости, чтобы их решал другой язык разработки), но опять же — заказчику все равно, ты разработчик — ты и выбирай инструмент. Если он бесплатен и хоть более-менее распространен — как правило всем кроме вас это до лампочки.
guyu
Эта основная проблема только для кодеров.
А для софтверного инженера, который звучит гордо, выбор путей решения (в том числе и выбор нужных именно ему самому инструментов) — даже, я бы сказал, рутина.
DenimTornado
Простите за профанский вопрос, я к вам из JS…
Почему в пункте 5 при "===" получаем false?
elmal
=== сравнивает значения указателей. То есть обычное == в Java. А == Ceylon отображается на .equals в Java.
lany
С этими равенствами, кстати, я уже в Котлине обжёгся.
Заметили опечатку? В джаве такая опечатка невозможна, а в Котлине/Цейлоне — легко (и я их видел в реальном коде).
elmal
Опечатку то я заметил.
Ну, в Ceylon я б такое написал как:
И вообще то, за все время написания на ceylon мне ни разу не приходилось использовать === оператор. Я даже забыл что он есть :).
lany
Разумеется, вы заметили опечатку, перед вами же две строчки кода, а не проект из тысячи файлов, в одном из которых опечатка. Зачем же был введён ненужный оператор? :-) В дизайне языка самое главное — не решить, что в него добавлять, а решить, что в него добавлять не стоит. С этим, кстати, очень большая проблема у груви (@RockPresident привет). Грувисты всегда хвастаются тем, что у них есть, но не могут похвастаться тем, чего у них нету. Котлин гораздо лучше именно потому, что в нём меньше фич. И то несмотря на юный возраст Котлина, в нём уже есть лишние вещи.
Cryvage
Там же сказано, что сравниваются ссылки. Это два разных объекта в памяти.
upd: немного опоздал.
NikNik77771
Кстати, т.к. Ceylon компилируется в JS его можно трактовать как очень мощно типизированный JavaScript.
elmal
Даже более того. Для JavaScript у Ceylon есть функционал Type Functions, в результате там с типами становится даже поинтереснее, чем на Java :).
DenimTornado
Понял, спасибо!
OLDRihard
А вот у меня вопросец. Я про этот яп узнал просто потому, что случайно набрел на него в сети. А почему он не выстрелил то? Он настолько страшный, что в него народ не пошел? Ей богу даже smalltalk чаще всплывает в инфополе чем этот яп.
elmal
Язык новый. На сам язык брошены ресурсы гораздо меньшие, чем на Kotlin. Раз так в 20 точно меньшие. Scala тоже очень долго не взлетала, а сейчас чуть ли не мейнстрим. В принципе только с начала этого года на Ceylon стало удовлетворительно писать используя IDEA. Eclipse ИМХО сильно на любителя. Посмотрим, может и выстрелить через определенное количество времени.
foldr
Вероятно, Red Hat не пиарят его так, как это делаю JetBrains, Google, Mozilla и Apple свои языки
potan
Аналог implicit там есть? В связи с развитием методологии Type Driven Development это важная фича.
Вообще что в нем есть, чего нет в Scala?
А вот необходимость писать return после Scala отпугивает.
elmal
implicit нет. Сознательно не стали делать, как и в Kotlin, чтобы не усложнять язык. В Kotlin и Ceylon есть хорошее решение проблем Null Safety. В результате чего нет необходимости использовать монады и усложнять код там, где можно без этого обойтись. Также в Ceylon гораздо лучшая система типов чем в практически любом языке, очень интересная типобезопасная рефлексия. Очень хорошие for comprehensions, практически как в Python и гораздо более читабельные, чем в scala. Очень хорошая поддержка Typles. И т.д, о чем отдельно. Собственно это первая часть статьи, где Ceylon выступал на поле Kotlin и оценивался по критериям Kotlin. Далее попробуем повоевать на поле Ceylon :)
potan
По мне так использование монад для Option удобно и позволяет писать общий код для разных контейнеров.
А for в Ceylon c монадами работает (Future и тп)?
elmal
При необходимости можно использовать такие же приемы, как на Java 8 и Scala. Например вся асинхронность к меня завернута в rxJava. И далее всякие композиции, map, flatmap и и.д. Хотя, если честно, предпочел бы async await функциональность, которой пока нет — это ИМХО более читаемо.
Если имеется в виду код:
То на ceylon он бы выглядел как:
Естественно это все нужно предварительно заврапить
potan
Я попробовал «async await», реализованный библиотекой в Scala и нашел эту функциональность ужасной, особенно когда пытаешся писать достаточно обобщенный код или работать со списками ассинхронных операций.
for в Ceylon получает блок? Я могу написать аналог
elmal
На ceylon это будет примерно так:
На деле это обычный for. Future в данном случае должна быть просто Iterable, просто возвращая одно значение. Для каждой итерации будет выполнен код, который идет после for. И далее это все обернется в ленивый Iterable. Если нужно не лениво, то вместо {for ...} будет [for ...] или можно {for ...}.sequence
potan
Хорошо.
Только скобки в for и let смущают, как-то не ожидаешь, что описаные величины внутри скобок будут доступны в объемлющем блоке. С таким с только в макросах сталкивался.
elmal
На самом деле для такой задачи можно обычным map и flatMap обойтись, без всяких for, читаемость будет по крайней мере на ceylon больше. for comprehensions не совсем для этого нужен. Но если очень хочется — почему нет :)?
elmal
Кстати, в принципе можно обойтись и без return. Если мы пишем в функциональной парадигме, то можно воспользоваться => оператором вместо {}, в этом случае return не нужен. Во многих случаях это несколько ухудшает читаемость кода, приходится пользоваться оператором let и тому подобное, но возможно. В Kotlin кстати примерно такая же ситуация с return, как и в Ceylon.
potan
Собственно, одна из причин, почему Kotlin меня отталкивает.
0xd34df00d
А зачем implicit нужен, кстати?
Я про скалу не знаю, но, судя по беглому гуглежу, на соответствующее хаскелевское расширение оно весьма похоже, а зачем оно в хаскеле может быть нужно для идиоматичного кода, я не знаю.
senia
Полного аналога на haskell скорее всего нет. Но, в частности, type class из haskell и trait из rust в scala — частный случай использования implicit.
В частности в котлине не написать метод, аналогичный mempty из haskell, Monoid[T].empty из scala и Default::default() из rust.
0xd34df00d
А в скале, оказывается, два implicit'а, implicit params и implicit classes. Речь идёт о втором, я так понимаю?
senia
Они связаны, но речь о первом. С точки зрения 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, но с тем важным отличием, что возможно не только добавление отдельных методов, но и приведение к интерфейсам.
Хотите подробней — я ниже ссылку кинул — лучше Одерски я не расскажу, но могу ответить на конкретные вопросы, если возникнут.
0xd34df00d
Интересный подход к реализации этаких тайпклассов. Интересно, правда, зачем сделано именно так, но, видимо, действительно лучше посмотреть видео, спасибо.
В случае хаскеля, кстати, тоже можно иметь несколько инстансов для одного и того же тайпкласса. Компилятор, правда, выдаёт предупреждение, если тайпкласс определён в модуле, отличном от определяющего тип либо от определяющего тайпкласс.
elmal
Как минимум это полезно при написании DSL. На Scala можно написать очень навороченные DSL практически любого синтаксиса. В этой области Scala рулит и рулит просто неимоверно. На Kotlin возможностей по написанию DSL будет поменьше, некоторых вещей будет не хватать. На Ceylon ситуация хуже, чем у Kotlin. За счет обязательной точки с запятой и из за того, что вызов функции всегда идет с указанием скобочек, и нельзя аргументы передавать через пробел. Но намного намного лучше, чем на Java.
Но вообще, 3 языка вполне имеют право на жизнь в настоящее время, у каждого из языков есть свои сильные и слабые стороны. Ни Scala, ни Kotlin, ни Ceylon, не являются серебряной пулей, подходящей ко всем задачам.
senia
Но если хотите объяснения что такое implicit, то лучше послушать Одерски: What to Leave Implicit. Только учтите, что все такие доклады больше рассчитаны на людей из java, а не из haskrll.
igormich88
Вопрос по пункту 8, если я правильно помню то фишка switch в том что строится таблица с адресами переходов и за счет этого код выполняется эффективно. А с такими конструкциями
не превращается ли switch просто в более красивую запись дерева условий?elmal
Со switch там интереснее. Как это под капотом, по существу не важно, это 100 раз могут безболезненно поменять
У switch там совсем другое назначение по сравнению c Java. Именно в Java я его практически не использую, кстати, ибо вероятность что я там ошибусь и поставлю break достаточно высока.
Предположим у меня тип
Или же что поинтереснее:
Если я делаю switch(p)
То сама IDE заставит меня и сгенерирует код для обработки всех возможных вариантов p
То есть
И если какого case не будет или не будет else, то ругнется компилятор, что я не все возможные значения отработал. За счет чего использование switch в Ceylon очень даже приветствуется.
Ну и также когда switch используется совместно с tuple, entry и деструктуризацией — получается весьма неплохой код, почти паттерн матчинг.
potan
Если я правильно понял, там полноценный pattern matching.
Ну и то, что это выражение, а не оператор, удобно.
elmal
К сожалению нет.
Для полноценного хотелось бы:
potan
Странно. Как без этого можно жить?
elmal
Жить можно без чего угодно. На Java нет даже близко ничего подобного, и народ как то не жалуется. Ибо про альтернативы не знает. Частые use case язык покрывает, остальное возможно появится в будущем. На практике очень часто используются кортежи и их деструктуризация, соответственно для значительной части задач этого хватает.
potan
С современной поддержкой IDE удобно заводить case class/data class на каждый чих. Кортежи как-то снижают преимущество от статической типизации.
elmal
Если бы были эти case class/data class. Но вообще, обещают алиасы класса на кортеж, но скорее всего будет не в этом релизе. Соответственно будет достаточно статически типизованно. Будет почти data class.
Надо понимать, что Ceylon это не Scala и не Kotlin. У него свои бест практики.
sshikov
Насчет близко — это вопрос немного субъективный. Вы javaslang видели?
elmal
Так это же библиотеки, а не сам язык. За счет библиотек можно сделать ОЧЕНЬ многое на любом языке. Вот только библиотеки — это не забыть добавить зависимости, не забыть про статик импорты, выглядит это чужеродно, большинство разработчиков про такое не знают ибо не всегда распространено, в конкретной конторе такую библиотеку могут вообще запретить к применению ибо каждую внешнюю либу нужно согласовывать в 10 инстанциях и т.д. Нужно следить за версиями библиотек и их зависимостями и тому подобное. Можно все, на любом языке. Хотя бы кодогенерацией :). Вопрос в лишних телодвижениях. В свое время я делал эти телодвижения и считал, что Java прекрасна ибо на ней можно все. А потом попробовал альтернативы, когда много полезного уже есть из коробки. И обратно то уже не хочется ...
sshikov
Я прекрасно понимаю, что это библиотека. Я в общем-то просто прокомментировал вот эту фразу:
>На Java нет даже близко ничего подобного
Это все-таки не совсем верно. Есть многое, хотя и не совсем таким же образом реализованное. Тот же ломбок, к примеру.
Ну и сделать такое можно далеко не в любом языке, и вообще говоря, когда не было лямбд, сделать такое в Java было практически нельзя (либо было чрезвычайно неудобно пользоваться).
Т.е. мысль-то моя простая — если язык позволяет сделать библиотекой то, что в другом языке требует изменений компилятора — это хороший, годный язык. Ну, типа лиспа :)
elmal
Когда не было лямбд, любители функциональщины прекрасно жили через анонимные классы :). И IDEA даже сворачивала эту громоздкость и код читался практически так же, как в случае с лямбдами :). А когда вышла восьмерка, тот код средствами той же IDEA стало возможным по хинту преобразовать в код с лямбдами, при этом практически ничего и переписывать не приходилось и все продолжило выглядеть так же, как и выглядело.
На деле, да факто куча недостатков Java можно сделать путем умной IDE. громоздкий синтаксис можно скрывать и т.д, сложные конструкции писать за тебя. Но что то мне подсказывает, что такой путь немного сомнительный. Это де факто получается другой язык, но жестко завязанные на конкретную IDE.
sshikov
Я вполне себе помню и применял functionaljava, guava (и еще пару аналогов). Но эстетически это порой было ужасно, а не прекрасно.
Ну и все-таки, размеры кода сильно сократились в итоге, что позволило его быстрее писать и легче читать.
lany
Ага, можно ещё Advanced Code Folding поставить, вообще другой язык будет :-)
guai
А по-моему, правильно и не сделали.
Вот 33 — это у нас что?
int, long, short, byte? double еще матчим или уже нет?
А если это явавский объект с несколькими конструкторами?
Кучу странных способов угадывания вкомпиливать в каждый кейс — это был бы overloading 2.0, от одного только что избавились :)
rraderio
Это int, также как в Java 33 это int а не long, short, byte, float, double
guai
pattern matching — отстой.
Это способ причесать антипаттерн, когда куча ветвлений делается по динамическому типу и значению.
Либо он будет ограничен небольшим набором системных типов, либо там такая каша из правил будет, что никто ее никогда не запомнит, и не будет понимать, а что конкретно будет и что не будет матчиться в том или ином случае.
Вот в данном случае Person(«Vasja», 33) — какие объекты матчим, какие нет? 33 вообще с каким полем сравниваем? По синтаксису похоже на параметр конструктора. А где мы его возьмём? Мы могли вообще никак не запоминать это значение, а параметр как-то заюзать в самом конструкторе, например. Или он приватный, рефлекшены подключать?
Допустим, как-то поняли, с чем сравнивать цифру. И что хотим именно int или Integer со значением 33.
Со строкой не меньше непоняток. Строка явы — наверное да, строка цейлона — тоже. Массив char'ов? Объект с toString()? StringBuilder/StringBuffer? Своя кастомная коллекция с char'ами? Учитываем регистр? Допустим, да. Как тогда описать матчинг, чтобы нет? Comparable#compare(«Vasja») == 0 — ?
Наследников Person матчим? А если у них другие конструкторы? А если мы еще и при компиляции не знаем, у кого какие? Опять рефлекшены? Прощай performance :(
Как переопределять матчинг для своего класса?
Плюс все радости оверлоадинга, когда код может внезапно без палева начать работать по-другому, потому что ты определил более специфичный метод/конструктор.
0xd34df00d
Не антипаттерн это (в общем случае). Посмотрите, как оно в хаскеле и товарищах сделано, никакой каши правил, все ясно и понятно, даже если всякими view patterns и pattern synonyms обмазываться.
guai
ну в хаскеле и нет такой каши из классов и интерфейсов
и уж тем более там нет надобности интероп с явой поддерживать :)
rraderio
Должен быть конструктор который принимает String и int.
Откуда вы знаете какой метод будет вызван? Который принимает массив char'ов? Объект с toString()? StringBuilder/StringBuffer? Своя кастомная коллекция с char'ами?
guai
я и не знаю в общем случае. String, CharSequence, Integer, int, Object в разных комбинациях могут быть. еще вариадик может быть.
поэтому оверлоадинг — отстой.
и поэтому его в цейлоне нет.
возвращать его второй раз в виде паттерн-матчинга — тоже отстой и тоже не стали так делать, за это я разрабов языка уважаю и прям расцеловал бы при случае :)
rraderio
Т.е. вы называете методы callStringAndInt?
elmal
На самом деле без оверлоадинга в Ceylon можно жить достаточно комфортно. Во первых, оверлоадинг при необходимости делается через Union Types. Метод один, он принимает определенные аргументы, а аргумент может быть или одного типа, или другого. А далее в обработчике либо сразу учитывать логику, либо уже делегировать специфичным непубличным методам. Во вторых, в Java большинство оверлоадинг методов нужны, так как там нет параметров по умолчанию. В третьих, если уж ну совсем приспичило с оверлоадингом, что ну никак не исхитриться (мне не доводилось с таким сталкиваться, но мало ли), то никто не запрещает написать нужную логику на Java, и вызывать этот оверлоадинг из Ceylon.
rraderio
Т.е. вместо того чтобы в compile-time знать какой метод надо вызывать, мы теперь будем в run-time определять?
Так ведь тогда и конструктор будет один и не будет неоднозначностей
elmal
Да, в рантайме. Да, перфоманс. Но про перфоманс я уже ответил.
По поводу оверлоадинга — любопытная статья относительно того, что функционал оверлоадинга весьма затруднил появление в Java лямбд из за чего было множество сложностей и багов.
https://objectteams.wordpress.com/2017/04/02/several-languages-java-8/
guai
нет.
фича уже есть, уже испортила ряд других фичей языка, просто не использовать ее и избавиться от ее негативного влияния не получится.
пользуюсь там, где это не вредно и к месту. и проектирую апи так, чтоб не ломались внезапно из-за оверлоадинга.
rraderio
Ну так и конструктор можно
и у вас обычно будет только один конструктор, так что неоднозначностей не будет
guai
если оверлоадинг не юзать, он не вредит сильно — ну да, так и есть. до тех пор пока не заюзаешь, и что-нибудь не отвалится, вообще в другой части кода зачастую, или вообще не у тебя :) всё компилится, всё ништяк, только перестало работать.
а еще своим существованием он портит рефлекшены, всегда, от этого уже не избавишься. я вынужден всё время указывать параметры при поиске методов, даже если вариант метода один. и то же самое со ссылками на методы.
ну и разрабы компиляторов явы замучились с ними, но это уже не мои проблемы. ну разве что компиляция была бы у меня пошустрее в противном случае…
rraderio
Вы пишите тесты? И как часто вы определяете более специфичный метод/конструктор?
guai
А это тут при чем?
Любой косяк языка можно подоткнуть административными костылями, бестпрактисами, стайлгайдами, тестами, тулзами, чекерами и т.п. На качество языка это влияет разве лишь косвенно.
Разрабы цейлона утверждают, что у него такое же свойство, как у хаскеля, образовалось: 95% написанного кода работают сразу, как удовлетворил компилятор еще до запуска. Ну и мой опыт пока этому не противоречит.
rraderio
Потому что не 100%. Вы все ровно пишите тесты и можете проверить какой метод вызвался. А с паттерн матчингом еще и код более читабельный.
guai
«читабельный» и «понимабельный» — разные вещи.
эти подкапотные правила надо в голове применить, чтоб понять, что происходит.
и если в языке не полтора типа данных, как в лиспе, правила не будут простыми.
0xd34df00d
В том и дело: я не хочу писать тесты на то, какой метод вызвался, пусть тайпчекер и свойства языка мне про это что-нибудь интересное гарантируют.
95% вместо 100% потому, что есть логические ошибки, связанные тупо с неправильно построенным алгоритмом.
rraderio
Как тайпчекер и свойства языка могут гарантировать что например вызвался метод отправвки эмейла при регистрации?
rraderio
Kotlin
и что вам тут не нравиться?
elmal
Знак ${}.
Приведу цитату из FAQ непосредственно от разработчиков языка https://ceylon-lang.org/documentation/1.3/faq/language-design/#string_interpolation_syntax:
Primarily because it looks a bit cleaner for defining text in user interfaces or other treelike structures.
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.
rraderio
Т.е. не нравится Java, но синтаксис уноследовали, а знак доллара не нравится, его не взяли.
elmal
Синтаксис Java унаследован частично. Например не public, а shared, не implements а satisfies и т.д. Из Java в основном идет имя типа слева от переменной, ключевой слово class и фигурные скобочки. Сам язык просто создавался с нуля, с учетом того хорошего, что было до этого.
guai
тут явно не яву имели в виду :)
sshikov
Вопрос спорный. И явно личные предпочтения тут перевесили.
P.S. Мне тоже `` напоминает кое-что из того, что хотелось бы забыть.
0xd34df00d
Лучше всего, когда это не в языке, а библиотекой, а язык просто даёт возможности такое сделать.
rraderio
Чем это лучше?
0xd34df00d
#{expr}
, хоть с backtick'ами.rraderio
Это скорее минус, если каждый будет делать как он хочет.
Самое часто используемое должно быть по умолчанию. Интерполяция и есть самое часто используемое в строках.
vba
Kotlin не вчера появился, но Ceylon по моему, старше Kotlin-а лет так на 5 или 6, у него первый стабильный релиз был в 2011, когда Kotlin только только зарождался.
kefirfromperm
Котлин до 1й стабильной версии шел долго. А у цейлона поддержки в идее не было.
rraderio
Ceylon в рантайме делает проверки?
elmal
n..m это просто синтаксический сахар для Range.
Внутри код вроде:
rraderio
Т.е. каждый раз проверяется в рантайме :(
А если нам надо чтобы цикл выполнялся только если n < m?
elmal
На выбор:
rraderio
Эээ, у меня функция принимает n и m
так вот, мне надо чтобы метод print исполнялся только если n < m
elmal
rraderio
Уж лучше с downTo. Кстати это не ключевое слово.
elmal
И тот и другой 2011. По сравнению со Scala, которая в 2003 появилась. Scala стала мейнстримом где то последние года 4, по крайней мере на scala можно найти работу без проблем. Kotlin стал настолько популярен, что на нем можно найти работу — тоже только в последние несколько лет. Но на Ceylon тоже можно работу найти, у меня получилось, когда я искал работу на Scala или Kotlin :):):).
Что считать стабильным релизом на самом деле еще и вопрос. Первая стабильная версия 1.0.0 в 2013 году. В гораздо более стабильном языке я лично зарепортил весьма немало багов, некоторые даже сам и поправил :).
RockPresident
Читаю все эти статьи и не пропадает впечатление что авторы просто не слышали о языке Groovy? В котором всё это уже есть лет 10, да плюс ещё огромное количество настолько же полезных возможностей. Стабильный язык, почти полная совместимость с .java кодом (и причём не такая где можно использовать другие java библиотеки, а в том смысле что можно просто взять .java файл, и он скомпилируется groovy сразу), полное решение всех verbosity проблем которые есть у джавы, куча паттернов позволяющих быстро прототипировать и вообще писать код, хорошая читаемость, узнаваемость, convention over configuration, свободный выбор между static type compilation/dynamic type compilation, (причём на уровне отдельных классов или даже методов!) и так далее.
Автор, если вы не пробовали Groovy, обязательно сделайте это.
NikNik77771
Присоединюсь к пожеланиям статьи о преимуществах по сравнению с Groovy, т.к. когда делали Ceylon Groovy уже был и Гэвин Кинг об этом знал. Значит Groovy чем то не устраивал.
fzn7
NIH синдром как он есть
AlexTheLost
Ещё была Scala.)
sshikov
Знаете, я в прошлой статье про котлин прокомментировал в том же духе — так мне минусов понаставили. Причем аргументировали один раз — что производительность groovy плохая (а подтвердить при этом ничем не удосужились). А по сути тут вопрос ровно тот же встает — а чем это лучше groovy? Который не просто появился давно, но и распространен весьма широко (как сам по себе, так и в виде gradle например, и не только), и большую часть ровно этих же преимуществ имеет (ну кроме компиляции в JS, пожалуй).
elmal
Либо его недостаточно пиарили. Либо я что то пропустил:
1) Как у groovy с иммутабельностью по умолчанию?
2) Как там дела с for comprehensions?
3) как там дела с деструктуризацией кортежей, причем чтоб деструктуризация была прямо в лямбдах?
4) Как там с женериками? Можно ли в groovy у List узнать в рантайме тип T?
sshikov
Вы пропустили 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 на уровне байткода, что мы видим на примере скалы).
RockPresident
Писать аннотацию Immutable самому даже не нужно, она уже есть: http://docs.groovy-lang.org/2.4.7/html/gapi/groovy/transform/Immutable.html
sshikov
Я когда писал «встроено в язык» именно это и имел в виду — аннотация уже есть, ее логику делать не нужно.
RockPresident
И самое интересное то что про производительность — везде где ищу информацию об этом — оказывается что нет никаких проблем с ней. Проблемы были когда-то в начале, все по одной лишь той причине что Groovy по умолчанию использует динамические типы. Потом встроили аннотацию статической компиляции, которая по сути делает производительность такой же как у Java.
На последнем конгрессе Groovy говорили что все текущие проблемы по сути из-за плохого пиара языка, в то время как технологически, по сегодняшним меркам, Groovy в выигрыше по сравниению со многими.
AnyKey80lvl
Обожаю Groovy! По-моему, недооцененный язык.
Но всё-таки хочется уточнить:
можно просто взять .java файл, и он скомпилируется groovy сразу
Это true только для java-файла до 1.7 включительно. Лямбды из 1.8, например, не скомпилируются.
sshikov
Да. Поддержка 1.8 вроде ожидается. Когда будет — непонятно.
mr-garrick
С нетерпением жду подобную статью про Groovy, Jython и т.п. :)
sshikov
С Jython все не так красиво. Насколько я понимаю, язык застрял на уровне версии 2.x. И версии 3.x похоже не будет никогда.
mr-garrick
Да, но и сам Python 2 ещё вполне востребован и похоже будет востребован ещё долго.
sshikov
Ну, если вас 2 устраивает, то версия 2.7 есть, в этом плане все более-менее хорошо. А с учетом того, что доступна вся инфраструктура Java, я бы даже сказал, что очень хорошо. Для некоторых задач. Я когда-то применял внутри Weblogic — и остался более чем доволен.
foldr
Уже не долго. Срок поддержки заканчивается в 2020 году. Django, ipython больше не поддерживают 2 ветку. В Heroku теперь версия по умолчанию — 3.6
Sirikid
И Scala, и, как оказалось, Kotlin не на 100% совместимы с Java, ваши комментарии по этому поводу?
Почему столько вариантов и чем они друг от друга отличаются? (Кроме очевидного
by
.)Очень многословнное и отформатировано совсем уж отвратно.
AlexTheLost
Что вы имеете ввиду? Насколько мне известно любой Java код можно вызвать из Scala, наоборот нет и это очевидно.) Scala более богатый на возможности язык чем Java.
elmal
Наоборот тоже прекрасно вызывается. Через одно место, громоздко, криво, но вызывается :).
Sirikid
Обычно (в контексте обсуждения языков для JVM) под 100% совместимостью понимается полный интероп в обе стороны.
elmal
Наоборот нет? Я помнится извращался, и вызывал Scala код не только из Java, но и из Ceylon.
senia
Это возможно в очень многих случаях, но есть исключения. Самое явное — макросы.
elmal
C Java как языком, или с некоторыми Java библиотеками и некоторыми тяжелыми серверами :)? Именно с взаимодействием с Java проблем нет. Как в одну, так и в другую сторону. Например я люблю в IDEA в момент точки останова делать evaluate expression, и вызывать непосредственно нужный метод. Я это любил делать в Java — я продолжаю таким заниматьсяи в Ceylon, хоть и мне приходится знать как ко всему этому достучаться из Java. Возможно с выходом Java 9 на начальном этапе будут какие то мелкие проблемы, а может и крупные, пока нормальной поддержки Java 9 не появится в языке. До версии Ceylon 1.3.0 были мелкие проблемы с взаимодействием с Java 8, но тоже вполне решаемые.
Включая, не включая, в обратном порядке, c шагом, проверка на нахождение в диапазон в if. Там можно и поболее вариантов привести.
Про это будет далее. Если коротко в этих языках исправлены фундаментальные недостатки Java. А именно — многословность, мутабельность по умолчанию, проблема c null safety. Весьма поднимает это все производительность разработки.
Sirikid
Как с языком. Например как использовать из Java овеществленные дженерики?
Об этом стоило написать в посте.
И об этом тоже.
elmal
Это тоже делается. Например через рефлексию. Грубо говоря, достается шаблон типа, он параметризуется нужным типом, и далее инстанцируется. Получается да, громоздко и неудобно, даже на цейлоне это не совсем тривиально. Но если есть такая необходимость — это все делается. На практике же лучше такого высшего пилотажа избегать, и если потребуется чтоб ceylon код вызывать из Java — лучше предоставить там Java API без всяких овеществленных дженериков. Если есть такая возможность, естественно.
Sirikid
Тогда глупо говорить про 100% совместимость.
NikNik77771
А как вы себе 100% совместимость представляете, если в java ее нет?
voddan
В Kotlin выкинули овеществленные дженерики чтобы со стороны Java код выглядел нормально. Без этой жертвы странно говорит про 100% или даже 99% совместимость с Java.
elmal
Я немного не понимаю какие тут большие проблемы. Вот код использования из Java ceylon ArrayList вместе с цейлоновскими же строками:
Специально не убирал явные имена пакетов, из за чего здесь это выглядит громоздко. Все проблема с овеществленными женериками из Java некрасивый $TypeDescriptor$ в конструкторе.
elmal
Единственная практическая проблема с вызовом из Java кода кода на Ceylon заключается в IDE. IDE да, пока не видит из Java цейлоновские классы. Из за чего внутри среды разработки Java код, вызывающий Ceylon код выглядит красным. Но это компилируется и запускается. И эта проблема актуально только в том случае, если проект изначально цейлоновский, и я мешаю там вызовы из Java в Ceylon. Если же цеплять jar, написанный на Ceylon к уже существующему проекту, то таких проблем не будет. Но рано или поздно это пофиксят, соответствующая бага давно заведена.
voddan
API где нужно всюду передавать
$TypeDescriptor$
не назовешь идиоматичным Java кодом.Я хотел еще раз подчеркнуть что в Kotlin трактовке "совместимость в обе стороны" подразумевает идиоматичный вид Java из Kotlin и Kotlin из Java. Мне кажется этот очень важный факт принижается в статье с отмашкой "где мы такое не видели".
senia
Навскидку (с цейлоном у меня даже хуже, чем с котлином): Цейлон позволяет отличить MyClass<Integer> от MyClass<String> в case. Достигается за счет доп. информации в инстансах дженериков. Сломается если MyClass<T> создан в java. Как это взаимодействует с джавовыми либами, создающими экземпляре на основе рефлексии (маршалинг, БД, etc), я затрудняюсь предугадать.
p9202583853
я не профи, но какая разница? Ceylon… Kotlin… все конструкции очень похожи друг на друга
наверное заминусуют сейчас люто, но!
вы видели современный swift? Там все тоже самое, различия минимальны
elmal
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
vlanko
Популярность вакансий у нас, относительно Java:
Scala — 11%
Groovy — 7.4% (тестировщики :)
Kotlin — 1.7% — просто Java с доп. требованиями Котлина.
Ceylon — 0
guai
Яве 22 года, скале 13 лет, цейлону с котлиным примерно по 5, от первого релиза, заявленного стабильным, что-то в районе полутора, вроде бы.
JB уже начали активный маркетинг не выдав толком релиз, RH еще ждут, полируют до сих пор, всё таки RH нацелен на кровавый интерпрайз, где лучше перебдеть.
elmal
Ceylon не 0. А в настоящее время минимум 1 вакансия, а то и вообще 3. В вакансии только нет ни слова про Ceylon, там Java стоит, кандидатов шокируют позднее :). Актуально для Питера, деньги не суперские, но и не совсем доширак, если кому интересно — можно в личку стучаться.
guai
Смысла переводить готовый большой проект на котлин я не вижу, а вот на цейлон — вижу.
Если уж заморачиваться, то хочется фичей по максимуму, прям чтоб с запасом :)
А проделать много работы и получить примерно то же самое, но с сахарком — по-моему, не стоит того.
С цейлоном сразу имеем и модульность и овеществленные дженерики, и систему типов, которую в скале только делают еще, и кмк скорее приведут этим к расслоению скалы на 2 версии, как с питоном произошло.
ДСЛ из коробки для всего, вообще без никакого обвязочного кода.
Про стопроцентную совместимость уже писали, что ее нет и быть не может.
Так вот, в цейлоне и не заявляют, что она есть, там предлагают наделать на нужные явавские либы модулей-оберток, минимизировать границу соприкосновения, и дальше остальное пилить на цейлоне. И это не сильно сложно. Скала доказала, что так жить можно.
В котлине замахнулись на более тесный интероп с явой, так, чтобы четкой границы вообще не было. И имхо это у них не выгорело, сами же пожертвовали null-safety на границе в угоду более казуальному процессу написания кода.
Цейлон целенаправленно фиксит косяки явы, а не просто добавляет сахарку, и не улетает в эмпиреи.
pioneer
Эх, не хватает async/await.
voddan
Как работают стандартные коллекции в Ceylon? Они "свои" или используются классы из JDK? Если я использую совместимость с Java, придется ли мне копировать (даже если и неявно) из коллекции в коллекцию?
elmal
Коллекции свои, написанные с нуля. Если совмещать Java и Ceylon коллекции — да, придется копировать. Синтаксис работы с Java коллекциями достаточно прозрачный и в принципе с Java коллекциями можно довольно комфортно работать. В основном на практике использую Java коллекции, когда мне нужно parallelStream использовать или если использую Java библиотеку. По умолчанию чаще всего стараюсь использовать не List, а Sequence или Iterable, а коллекции только когда реально необходимо. Ибо синтаксис Sequence и Iterable ИМХО гораздо чище. Если коллекции реально нужны, приоритет отдаю цейлоновским, если нельзя (например мне нужны коллекции из пакета Concurrent, а у цейлона на уровне языка поддержки многопоточности нет вообще) — используем Java коллекции. Один разок я даже Scala коллекции решил заюзать, завелось без проблем.
voddan
Звучит так как будто при неосторожном смешивании библиотек производительность начинает резко просидать. Так себе ситуация, IMHO. Подход Kotlin с черной магией в компиляторе в этом смысле сильно лучше.
Я понимаю что в этой статье вы не ставили себе задачу сравнить все за и против, но вообще это был бы один из минусов Ceylon.
elmal
На самом деле, когда реально важна производительность, там вообще не до коллекций :). Уже и на 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 библиотеки, которые являются обертками над сишными библиотеками. И узким местом является именно сишная библиотека. не подготовка данных, а именно тупой расчет.
Если уж на то пошло, улучшенные дженерики с информацией о типе дженерика в рантайме с точки производительности очень даже не бесплатны и в узких местах узнавать информацию о типе не стоит выяснять. В узких местах вообще то многое не следует делать :).