Ceylon (язык программирования)

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 20:20, 1 июня 2016.
Ceylon
FileTeplov2.png
Парадигма Императивный, Объектно-ориентированный
Спроектировано Red Hat
Первый   появившийся 2011
Стабильная версия 1.2.0 / 29 октября 2015
Лицензия Apache License 2.0
Расширение файла .ceylon
Портал: http://ceylon-lang.org
Под влиянием
Java, JavaScript, C#

Ceylon — императивный язык программирования, ориентированный на командную разработку крупных приложений[1].

Первый релиз языка Ceylon M1 был выпущен 17 декабря 2011 года и охватывает примерно 80% запланированных возможностей языка[1].

Принципы дизайна языка:

  • Читабельность кода — параметр, значение которого возрастает с ростом размера команды разработчиков[1].
  • Предсказуемость — поведение компилятора и программы должно быть интуитивно понятно, даже если ради этого придется пожертвовать некоторыми возможностями[1].
  • Инструментарий — разработка программ ведется значительно продуктивнее при наличии среды разработки (IDE), поэтому Ceylon должен иметь свою IDE. Кроме того, сообщения об ошибках должны быть максимально информативны[1].
  • Модульность, значение которой возрастает с ростом размеров разрабатываемых программ[1].
  • Метапрограммирование: многие библиотеки и сложные фреймворки основаны на возможности писать код, который обрабатывает другой код[1].

Синтаксис языка похож на Java и C#. Ceylon в значительной мере основан на Java, но использует только лучшие решения, исправляя и улучшая неудачные[1].

Содержание

Особенности языка[2]

  • Статическая типизация (тип любого значения любого выражения может быть определён без исполнения программы), позволяющая выявлять ошибки на этапе компиляции, а не в процессе исполнения;
  • Отсутствие специальных типов, всё реализовано в виде объектов;
  • Именованные и опциональные параметры;
  • Nullable-типы (кроме значений базового типа, допускается использование состояний NULL);
  • Отсутствие необходимости явного указания геттеров/сеттеров (getter/setters);
  • Определение типов для локальных блоков (через ключевое слово "local");
  • Удобная организация работы с последовательностями (массивами);
  • Реализация функций высшего порядка, аргументом или возвращаемым результатом в которых выступают другие функции;
  • Использование для присвоения первоначальных значений (инициализации переменных) оператора ":=";
  • Новый синтаксис интерполяции строк;
  • Новые типы: Natural, Numeric и т.п.
  • Классы, методы и атрибуты выглядят одинаково;
  • Использование для определения существующих языковых концепций новых ключевых слов: shared, satisfies, assign, variable, local;
  • Упрощение уровней public, protected, private access, visibility;
  • Определение inline-функций в стиле Smalltalk.

Ceylon как продолжение или замена языку Java

Гэвин Кинг, возглявляющий проект Red Hat задался вопросом: как должен был бы выглядеть язык с учетом уроков, извлеченных из преимуществ и недостатков языка Java и SDK? Его ответом стал Ceylon, статически типизированный язык, который сохраняет некоторые из лучших особенностей языка Java (и работает на JVM), но при этом обладает лучшей читаемостью, встроенной модульностью, а также включает ряд возможностей функциональных языков, такие как функции высшего порядка. Ceylon также включает в себя возможности C и Smalltalk. Во многом похожий на Java, этот новый язык ориентирован на бизнес-приложения, но при этом гибок и полезен и в других областях[3].

Некоторые называют Ceylon «убийцей» Java (возможно, из-за вопросов о будущем языка Java), но на самом деле Ceylon работает на JVM, так что это расширение Java-технологии, а не ее замена. Использование виртуальной машины Java для поддержки выполнения Ceylon — это идеальная модель, потому что это означает переносимость Ceylon (как и Java) на все множество архитектур, которые в настоящее время поддерживают JVM[3].

Типы данных в Ceylon[3]

Ceylon включает в себя традиционный набор типов, которые реализуются как обычные классы:

  • Natural. Беззнаковое целое, включая 0.
  • Integer. Целое число со знаком.
  • Float. Число с плавающей точкой.
  • Whole. Целое число произвольной точности со знаком.
  • Decimal. Десятичная дробь произвольной точности и произвольной величины.

По умолчанию типы Natural, Integer и Float 64-разрядные, но вы можете снабдить их аннотацией small, чтобы указать 32-разрядную точность.

Операторы Ceylon

! (Отрицание)

Оператор логического отрицания (!) — это унарный оператор, который выполняет над своим операндом операцию НЕ.Он задан для типа Boolean и возвращает true тогда и только тогда, когда его операнд имеет значение false.

Пример

Boolean true_ = !false;

!= (Не равно)

Оператор неравенства (!=) возвращает значение false, если его операнды равны, в противном случае — значение true.Операторы неравенства предопределены для всех типов, включая строку и объект.

Пример

void m(Object x, Object y) {
    Boolean identical = x != y;
}

% (Остаток от деления)

Оператор % вычисляет остаток после деления первого операнда на второй.Все числовые типы имеют предопределенные операторы остатка. Пример

Integer two = 5 % 3;

%= (Присваивание остатка)

Оператор присваивания остатка.

Пример

variable Integer num = 10;
num %= 2; // half num

& (Set intersection)

Оператор & может функционировать как унарный или как бинарный оператор.

Пример

void m(Set<Integer> primes, Set<Integer> evens) {
    Set<Integer> two = primes &amp; evens;
}

&& (and)

Условный оператор (&&) выполняет логическое AND над операндами типа boolean, но вычисляет второй операнд только при необходимости.

Пример

Boolean false_ = true &amp;&amp; false;

&&= (and assign)

Пример

variable Boolean a = true;
Boolean b = false;
a &amp;&amp;= b; // a becomes false

&= (Set intersect assign)

Оператор назначения AND.

Пример

void m(Set<Integer> primes, Set<Integer> evens) {
    variable Set<Integer> two = primes;
    two &amp;= evens;
}

() (invoke)

Круглые скобки используются для указания порядка выполнения операций в выражении, а также для выполнения следующих задач:

  • Определение операций приведения или преобразования типов.
  • Вызов методов или делегатов.

Пример

print("hello, world!");       // positional style
print{                        // named-arguments style
    line="hello, world";
};
MyClass instance = MyClass(); // invoking a class to get an instance

* (product)

Оператор умножения (*), который вычисляет произведение двух операндов.

Пример

Integer six = 3 * 2;

** (scale)

Пример

value four_plus_6i = 2 ** Complex(2, 3);

*= (Двоичное умножение)

Оператор присвоения двоичного умножения.

Пример

variable Integer num = 1;
num *= 2; // double num 
num *= num; // square num

+ (Сумма)

Оператор + может функционировать как унарный или как бинарный оператор.

Пример

Integer three = 1 + 2;
String concatenated = "foo" + "bar";

+ (unary plus)

Пример

Integer one = +1;
Integer minusOne = +(-1);

++ (increment)

Оператор инкремента (++) увеличивает свой операнд на 1.Оператор инкремента может находиться как перед операндом, так и после него:

Пример1

variable Integer num = 1;
num++;

Пример2

variable Integer num = 1;
++num;

+= (add assign)

Оператор назначения сложения.

Пример

variable Integer num = 1;
num += 1; // increment num by 1
num += num; // increment num by 2

-(difference)

Пример

Integer one = 3 - 2;

- (unary minus)

Пример

Integer minusOne = -1;

-- (decrement)

Пример 1

variable Integer num = 1;
num--;

Пример 2

variable Integer num = 1;
--num;

-= (subtract assign)

Пример

variable Integer num = 4;
num -= 1; // decrement num by 1
num -= num; // decrement num by 3

-> (entry)

Пример

Entry<Integer, String> intName = 1 -> "One";

. (member)

Пример

String[] args = process.arguments;

.. (spanned range)

Пример

Range<Integer> ten = 1..10;

y:z (measured range)

Пример

Range<Integer> ten = 1:10;

/ (quotient)

Пример

Integer three = 6 / 2;

/= (divide assign)

Пример

variable Float num = 1.0;
num /= 2.0; // half num

< (less than)

Пример

void m<T>(T x, T y) 
  given T satisfies Comparable<T> {
    Boolean less = x < y;
}

<= (less than or equal)

Пример

void m<T>(T x, T y) 
  given T satisfies Comparable<T> {
    Boolean lessOrEqual = x <= y;
}

<=> (compare)

Пример

void m<T>(T x, T y) given T satisfies Comparable<T> {
    Comparison cmp = x <=> y;
}

= (assign)

Пример

variable Integer num = 1; // assign
num = 2; //assign
Integer three = 3 // specify

== (equal)

Пример

void m(Object x, Object y) {
    Boolean identical = x == y;
}

=== (identical)

Пример

void m(Identifiable x, Identifiable y) {
    Boolean identical = x === y;
}

> (greater than)

Пример

void m<T>(T x, T y) 
  given T satisfies Comparable<T> {
    Boolean more = x > y;
}

>= (greater than or equal)

Пример

void m<T>(T x, T y) 
  given T satisfies Comparable<T> {
    Boolean greaterOrEqual = x >= y;
}

?. (null-safe attribute)

Пример

void m(Integer? num) {
    Integer? int = num?.positiveValue;
}

?. (null-safe method)

Пример

void m(Integer? num) {
    Integer?(Integer) plus = num?.plus;
}

[] (lookup)

Пример

void m(Integer[] seq) {
    Integer? first = seq[0];
}

* (spread)

Пример

void spreadIterable(String* names) {
    // note names is a variadic parameter
}

{String*} names = { "Tom", "Gavin" };

// Invocation using listed arguments
spreadIterable("Tom", "Gavin");

// Invocation using a spread iterable argument
spreadIterable(*names);

*. (spread attribute)

Пример

{String+} names = {"foo", "bar", "baz"};
{Integer+} sizes = names*.size;

*. (spread method)

Пример

{String+} names = {"foo", "bar", "baz"};
{String+} initials = names*.initial(1);

x[y..z] (span)

Пример

String[] names = {"foo", "bar", "baz"};
String[] firstAndSecond = names[0..1];
String[] secondAndThird = names[1..2];

x[y...] (upper span)

Пример

String[] names = {"foo", "bar", "baz"};
String[] secondAndThird = names[1...];
String[] third = names[2...];
String[] emptySequence = names[3...];

x[...z] (lower span)

Пример

String[] names = {"foo", "bar", "baz"};
String[] foo = names[...0];
String[] foobar = names[...1];
String[] emptySequence = names[...-1];

x[y:z] (measure)

Пример

String[] names = {"foo", "bar", "baz"};
String[] foo = names[0:1];
String[] barBaz = names[1:2];
String[] empty = names[1:0];

^ (power)

Пример

Integer eight = 2 ^ 3;

| (Set union)

Пример

void m(Set<Integer> odds, Set<Integer> evens) {
    Set<Integer> ints = odds | evens;
}

|= (Set union assign)

Пример

void m(Set<Integer> odds, Set<Integer> evens) {
    variable Set<Integer> all = odds;
    all |= evens;
}

|| (or)

Пример

Boolean true_ = true || false;

||= (or assign)

Пример

variable Boolean a = false;
Boolean b = true;
a ||= b; // a becomes true

{} (invoke)

Пример

print("hello, world!");       // positional style
print{                        // named-arguments style
    line="hello, world";
};
MyClass instance = MyClass(); // invoking a class to get an instance

~ (Set complement)

Пример

void m<Dog>(Set<Dog> dogs, Set<Dog> blackDogs) 
  given Dog satisfies Object {
    Set<Dog> nonBlackDogs = dogs ~ blackDogs;
}

~= (Set complement assign)

Пример

void m<Dog>(Set<Dog> dogs, Set<Dog> blackDogs) 
  given Dog satisfies Object {
    variable Set<Dog> nonBlackDogs = dogs;
    nonBlackDogs ~= blackDogs;
}

else

Пример

void m(Integer? num) {
    Boolean haveNum = num exists;
}

exists

Пример

void m(Integer? num) {
    Boolean haveNum = num exists;
}

in

Пример

void m(Object x, Category y) {
    Boolean contained = x in y;
}

is

Пример

void m(Object? obj) {
    Boolean isNumber = obj is Number<out Anything>;
    Boolean isNull = obj is Null;
}

nonempty

Пример

void m(Integer[] nums) {
    Boolean haveNums = nums nonempty;
}

of

Пример

void m(Anything obj) {
    Object|Null maybeNull = obj of Object|Null;
}

then

Пример

void m(String s) {
    String s2 = s.empty then "hello";
}

Операции Cyelon

  • assert
  • break
  • continue
  • Condition lists
  • Expression statements
  • for
  • if statement
  • import
  • return
  • Specification statements
  • Destructuring specification
  • switch statement
  • throw
  • try
  • while

Примеры

Hello, World!

void hello() {
    print("Hello, World!");
}

Факториал числа

В этом примере факториалы вычисляются итеративно. Ключевое слово variable указывает на то, что значение переменной fact будет изменяться позднее (в Java, напротив, ключевое слово final указывает на то, что значение переменной изменяться не будет). Тип Integer позволяет хранить значения факториалов без переполнения. Оператор конкатенации аргументов команды print не требует отдельного оператора, но при этом первый и последний элемент из списка конкатенируемых должны быть строками.

void factorial() {
    variable Integer fact := 1;
    for (i in 0..16) {
        print("" i "! = " fact "");
        fact *= i + 1;
    }
}

Числа Фибоначчи

В этом примере используется итеративное вычисление чисел Фибоначчи.

void fibon() {
    variable String output := "";
    variable Integer fib1 := 0;
    variable Integer fib2 := 1;
    variable Integer fib3;
    for (i in 1..16) {
        output := "" output "" fib2 ", ";
        fib3 := fib1 + fib2;
        fib1 := fib2;
        fib2 := fib3;
    }
    print("" output "...");
}

Будущее Ceylon

Кинг отмечает, что Ceylon является результатом коллективной работы, и призывает разработчиков и тестировщиков программного обеспечения помогать в проектировании, построении и проверке языка и SDK. Этот призыв также может стимулировать отклики от пользователей Java, чтобы поддержать их переход на Ceylon. Кинг по-прежнему ничего не сообщает о текущем состоянии Ceylon и только говорит, что существуют спецификация языка и грамматика, написанная на ANTLR (Another Tool for Language Recognition).[3]

Примечание

  1. 1,0 1,1 1,2 1,3 1,4 1,5 1,6 1,7 Ceylon (рус.)
  2. Компания Red Hat выпустила язык программирования Ceylon 1.2  (рус.)
  3. 3,0 3,1 3,2 3,3 Ceylon: Реальный прорыв или просто очередной язык? (рус.)

Ссылки