![image](https://habrastorage.org/getpro/habr/post_images/1e0/da3/8d8/1e0da38d872cd7bb0bbcf7c1de3fd96a.png)
Совсем недавно на Хабре появилась статья, которая дает не совсем верное представление о текущем положении вещей в Scala-сообществе. У читателя создается ложное впечатление о застое и загнивании в экосистеме Scala. В этой статье я хотел бы исправить это и рассказать о недавно вышедших новинках и будущих изменениях.
В мае 2016 году на конференции Scala Days в Нью-Йорке Мартином Одерски была представлена презентация, описывающая настоящее и будущее языка Scala.
Scala 2.12
В ноябре 2016 года вышла новая версия компилятора Scala версии 2.12, в которой трейты компилируются прямо в Java-интерфейсы с дефолтными методами, а лямбда-функции в Scala и Java стали полностью совместимыми, так что теперь их можно вызывать в обоих направлениях одинаково удобно. Также это способствовало улучшению производительности Scala-кода на JRE 8.
Scala 2.13
На новый релиз комилятора scalac намечен рефакторинг стандартной библиотеки. Особое внимание будет уделено коллекциям и возможно стандартная библиотека будет разделена на компактное ядро и платформу, в которую войдет все, что не попало в ядро. Кажется, будто, разработка scalac буксует на месте. Возможно, это отчасти правда, потому самая мякотка разрабатывается сейчас для нового компилятора Scala, окрещенного Dotty в честь теории зависимых типов, на которой он основан.
Scala Dotty
Разработка нового компилятора ведется уже несколько лет силами команды EPFL, возглавляемой Мартином Одерски. Кроме него в ядро команды входит еще 5 человек, включая хабровчанина Дмитрия Петрашко aka darkdimius. Основной для новой версии языка является Dependent Object Types calculus, разработанный Мартином Одерски специально для нужд Scala.
Из-за новой структуры компилятора, суть которой объясняется в этом видео, скорость компиляции уже вдвое быстрее, чем в scalac. И это еще при учете того, что разработчики еще даже не приступали к оптимизации компилятора. Так что все уже устаревшие на данный момент мифы про неудобство тормозной компиляции Scala будут окончательно развенчаны.
В Dotty будет обновлена система типов, будут убраны неиспользуемые возможности языка. Многие вещи будут сильно упрощены. Но это все абстрактные слова. Давайте побыстрее перейдем к примерам.
Сначала пройдемся по тому, что убрали за ненужностью.
- Процедурный синтаксис
- Классы с DelayedInit
- Макросы, основанные на рефлексии
- Ранняя инициализация трейтов
- Экзистенциальные типы
- Проекции обобщенных типов
- XML-вставки в код
Вместо этого всего были добавлены новые улученные фичи:
- Теперь вместо with в типе переменной добавлены типа-пересечения
val a : A & B
- Теперь вместо проблем с Either у нас есть типы-объединения. В переменной может храниться или тип А или тип B. Это устраняет кучу бойлерплейта
val a : A | B
- Наконец-то исправлены тюплы в лямбда-выражениях.
//Было val numbersAndLetters = List((1,"A"), (2,"B")) numbersAndLetters.map { case (number, letter) => ... } //Стало numbersAndLetters.map((number, letter) => ...)
- В трейтах можно объявлять параметры
trait WithParameter(name:String) { ... }
- Операторы равенства == и неравенства != теперь типобезопасны
- Параметрам-типам стало можно присваивать имена. Стала возможна частичная параметризация.
trait Map[type Key, type Value] Map[Key = Int]
В текущем виде компилятор dotc можно опробовать на этом тестовом проекте. В будущем же обещано добавить в язык новых возможностей.
- Неявные функциональные типа
type CtxS = implicit Context => S def f(x:T):CtxS = { ... implicitly[Context] ... } f(e) //Context argument is passed implicitly
- Наряду с обычными функциями появятся эффекты, гарантирующие чистоту
A => B (can be impure) A -> B (pure)
- Обычные типы не смогут быть null по дефолту. Значения, пришедшие из Java-кода всегда будут опциональными.
T? = T | Null val stream: PrintStream? = System.out.printStream
- Магическое число 22 больше не будет пугать Scala разработчиков. Tuple22/Function22/Product22 станут историей
type (S, T, U) = (S, (T, (U, Unit)))
- Новый тип данных records. Что-то типа тюплов с именами. Примера кода нет. Это пока что самый мистический концепт из представленных.
Также в Dotty спроектирована система Tasty, позволяющая не перекомпилировать библиотеки под каждую версию компилятора, что было проблемным в Scala 2. И по сравнению со второй версией Scala в Dotty обещают сделать хорошие объяснения ошибкам при компиляции.
Dotty Linker
Венцом на короне Dotty является Linker, разрабатываемый Дмитрием Петрашко. Это оптимизатор, позволяющий компилировать код исключительно для тех типов, которые реально используются. Это позволяет добиться серьезного уменьшения количества кода и увелечения производительности. С помощью линкера сильно улучшается даже производительность подключаемых библиотек. Подробнее об этом чудо-оптимизаторе можно узнать в этом видео.
Scala meta
Вместо старых макросов выходят новые удобные Scala Meta макросы, разрабатываемыемые Евгением Бурмако. Пока что они вышли только для Scala 2.11 и только для аннотаций, но не методов. Но уже можно сказать, что они получились гораздо удобнее предыдущей версии. Теперь объявление макроса и его имплементация не разделены, а работа с синтаксическими деревьями просто великолепна. Также scala.meta работают с исходными деревьями, а не с уже слегка преобразованными как макросы, основанные на старой scala.reflect.
Подробнее о них можно почитать в этом туториале.
Scala JS
Scala.js компилирует код на Scala в высокопроизводительный Javascript код. Вместе со Scalatags и ScalaCSS становится возможна полноценная разработка веб-фронтенда. Огромным плюсом является возможность расшаривать сущности между клиентом и сервером, и использовать вместо явного определения HTTP API, удаленный вызов процедур. В последние несколько лет появилось несколько хорошо отлаженных и используемых в продакшене фреймворков с реактивными биндингами вроде Udash. Многие разработчики используют Scala.js, так как не хотят мучатся с динамическим и «странным» JS. Приведу пример, используемый в официальной документации.
javascript> ["10", "10", "10", "10"].map(parseInt)
[10, NaN, 2, 3] // What???
scala> List("10", "10", "10", "10").map(parseInt)
List(10, 10, 10, 10) // That's it
Scala Native
Недавно вышел Scala Native — компилятор в нативный бинарник, основанный на LLVM. Это позволяет писать на Scala мгновенно запускающийся код и использовать низкоуровневые структуры данных.
Macroid и RoboScala
Так как Scala компилируется в Java код, то является возможным использования этого языка для разработки под Андроид. Для этого существует специализированная библеотека Macroid, предоставляющая удобное для использование Android API. Так же существует возможность cкомпилировать Scala код по IOS с помощью RoboScala — обертки вокруг RoboVM
ScalaFX
Для разработки десктопного софта существует библиотека ScalaFX, являющаяся оберткой вокруг известной JavaFX.
Заключение
Хоть статья и получилась сильно сумбурной, но она может послужить хорошим списком ссылок на различные инструменты компиляции Scala под различные платформы, и источником информации о будущих наработках и фичах. Все представленные в статье инструменты и компиляторы активно разрабатываются, улучшаются и используются. Так что говорить о каком-либо застое или даже упадке в экосистеме Scala не приходится.