Нова версія Scala 3 принесла багато покращень і нові можливості. Тут наведено короткий огляд найважливіших змін. Якщо ви хочете розібратись детальніше глибше, у вашому розпорядженні є наступні посилання:
- Книга по Scala 3 націлений на розробників-початківців мови Scala.
- Конспект синтаксису надає формальний опис нового синтаксису.
- Довідник з мови дає детальний опис змін від Scala 2 до Scala 3.
- Посібник з міграції надає вам всю інформацію, необхідну для переходу від Scala 2 до Scala 3.
- Посібник для внесення змін в Scala 3 глибше занурюється в компілятор, включаючи посібник із розв’язання проблем.
Що нового в Scala 3
Scala 3 - це повне перероблення мови Scala. Було змінено багато аспектів системи типів на більш принципові. Хоч це і надає нові можливості (наприклад, об’єднання типів), але в першу чергу це означає, що у вашій роботі стає менше системи типів та наведення типів. Також значно покращено процес перевантаження.
Нове і яскраве: Синтаксис
Окрім багатьох (невеликих) очищень, синтаксис Scala 3 пропонує такі покращення:
- Новий «тихий» синтаксис для керуючих структур, таких як
if
,while
таfor
(новий синтаксис керуючих структур) - Ключеве слово
new
тепер опціональне (або creator applications) - Опціональні дужки привертають до стилю програмування на основі відступів
- Зміна символу підстановки типів з
_
на?
. - Імплісіти (та їх синтаксис) були ґрунтовно переглянуті.
Впертість: контекстні абстракції
Одним з основних концептів Scala було (і залишається певною мірою) надання користувачам невеликого набору потужних можливостей, які можна комбінувати заради великої (а іноді навіть непередбачуваної) виразності. Наприклад, implicits використовувалися для моделювання контекстної абстракції, для вираження обчислення на рівні типів, моделювання типів-класів, виконання неявних приведень, кодування розширення методів та багато іншого. Базуючись на цих прикладах використання, Scala 3 використовує дещо інший підхід і фокусується на намірі, а не на механізмі. Замість того, щоб пропонувати одну дуже потужну функцію, Scala 3 пропонує кілька спеціальних мовних конструкцій, що дозволяють програмістам прямо висловлювати свої наміри:
-
Абстрагування над контекстною інформацією. Ключове слово using дозволяє програмістам абстрагуватися від інформації, яка доступна в контексті виклику і повинна передаватися неявно. Конструкція using є удосконаленням implicit зі Scala 2 та може бути визначена за типом, звільняючи сигнатури функцій від термів, на які ніколи не посилаються явно.
-
Надання екземплярів класів типів. Наведені екземпляри дозволяють програмістам визначати канонічне значення певного типу. Це робить програмування з класами типів простішим без витоку деталей реалізації.
-
Ретроспективне розширення класів. У Scala 2 методи розширення повинні бути закодовані за допомогою неявних перетворень або неявних класів. На відміну від цього, у Scala 3 методи розширення тепер безпосередньо вбудовані в мову, що призводить до кращих повідомлень про помилки та покращеного виведення типу.
-
Відображення одного типу як іншого. Неявні перетворення були перероблені з нуля як екземпляри класу типів
Conversion
. -
Контекстні абстракції вищого порядку. Абсолютно нова можливість контекстних функцій робить контекстні абстракції first-class citizen. Вони є важливим інструментом для авторів бібліотек і дозволяють стисло виразити домен-специфічні мови.
-
Дієвий відгук від компілятора. Якщо неявний параметр не може бути розв’язаний компілятором, то надаються пропозиції імпорту, що можуть розв’язувати проблему.
Скажи що маєш на увазі: покращення системи типів
Окрім значно покращеного виведення типів, система типів Scala 3 також пропонує багато нових функцій, надаючи вам потужні інструменти для статичного вираження інваріантів у типах:
-
Перерахування. Enum був перероблений, щоб добре поєднуватися з кейс-класами та сформувати новий стандарт для вираження алгебраїчних типів даних.
-
Непрозорі типи. Сховайте деталі реалізації за псевдонімом непрозорого типу без зниження перфомансу! Непрозорі типи замінюють класи значень і дозволяють налаштувати бар’єр абстракції без додаткових накладних витрат.
-
Типи перетину та об’єднання. Нові засади системи типів призвели до введення нових можливостей системи типів: екземпляр типу Intersection, як
A & B
, є екземпляром обох типів іA
іB
. Екземпляр типу Union, якA | B
, є екземпляром абоA
абоB
. Обидві конструкції дозволяють програмістам гнучко обмежувати типи поза межами ієрархії наслідування. -
Залежні типи функцій. Scala 2 вже дозволяє типам результату залежати від (значення) аргументів. У Scala 3 тепер можна абстрагуватися над цим шаблоном і виразити залежні типи функцій. В типі
type F = (e: Entry) => e.Key
результат залежить від аргументу! -
Поліморфні типи функцій. Як і типи функцій залежності, Scala 2 підтримувала методи, які дозволяють параметри типу, але не дозволяла абстрагуватися над цими методами. У Scala 3, поліморфні типи функцій, наприклад
[A] => List[A] => List[A]
абстрагується над функцією, що приймає аргумент типу на додачу до аргументів значень. -
Лямбда типу. Те, що виражалося з використанням плагіна компілятора в Scala 2 тепер є першокласною особливістю в Scala 3: Лямбда типу — це функції рівня типів, які можна передавати як аргументи типу (вищого роду) без визначення допоміжного типу.
-
Відповідність типів. Замість того, щоб кодувати обчислення на рівні типу з використанням імплісітів, Scala 3 пропонує пряму підтримку відповідності за типами. Інтеграція обчислень на рівні типів у процес перевірки типів дозволяє покращити повідомлення про помилки та усуває необхідність у складному кодуванні.
Переосмислено: об’єктно-орієнтоване програмування
Scala завжди була на межі між функціональним програмуванням та об’єктноорієнтованим програмуванням – і Scala 3 розширює межі в обох напрямках! Вищезгадані зміни в системі типів і перероблення контекстних абстракцій роблять функціональне програмування легшим, ніж раніше. Водночас наступні нові функції дозволяють добре структурувати об’єктноорієнтовані проєкти та підтримують найкращі практики.
- Pass it on. Трейти наближаються до класів і тепер також можуть приймати параметри, що робить їх ще більш потужними як інструмент для модульної декомпозиції.
- План розширення. Класи розширення, які не призначені для наслідування, є давньою проблемою в об’єктноорієнтованому програмуванні. Для розв’язання цього питання, відкриті класи вимагають у розробників бібліотек явно позначити класи як відкриті.
- Приховати деталі реалізації. Утилітні трейти, які іноді реалізують поведінку, не повинні входити до складу виведених типів. У Scala 3, такі трейти можуть бути позначені як прозорі приховуючи наслідування від користувача (у виведених типах).
- Композиція понад спадковістю. Це поняття широко згадується, але є важким у реалізації. Але не з export у Scala 3’s: симетричні до імпорту, експорти дозволяють користувачеві визначати псевдоніми для вибраних членів об’єкта.
- Більше без NPE. Scala 3 безпечніша, ніж будь-коли: явний null виводить
null
з ієрархії типів, допомагаючи статично виловлювати помилки; додаткові перевірки для безпечної ініціалізації виявляють доступ до неініціалізованих об’єктів.
Батарейки в комплекті: метапрограмування
Хоча макроси в Scala 2 були лише експериментальною функцією, Scala 3 поставляється з потужним арсеналом інструментів для метапрограмування. Посібник по макросах містить детальну інформацію про різні об’єкти. Зокрема, Scala 3 пропонує наступні можливості для метапрограмування:
- Inline. Як відправна точка, inline дозволяє редукувати значення та методи під час компіляції. Ця проста функція вже охоплює багато варіантів використання і в той же час є точкою входу для більш розширених функцій.
- Операції під час компіляції. Пакет
scala.compiletime
містить додаткову функціональність, яку можна використовувати для реалізації вбудованих методів. - Цитування блоків коду. Scala 3 додає нову можливість квазі-цитування коду, що надає зручний інтерфейс високого рівня для побудови та аналізу коду. Побудувати код для додавання одиниці до одиниці так само просто, як і
'{ 1 + 1 }
. - API рефлексії. Для більш просунутих випадків використання quotes.reflect забезпечує більш детальний контроль для перевірки та створення дерев програм.
Якщо ви хочете дізнатися більше про метапрограмування в Scala 3, пропонуємо подивитись на наш посібник.