Название Scala происходит от слова scalable, и в соответствии с этим названием язык Scala используется для поддержки загруженных веб-сайтов и анализа огромных наборов данных. В этом разделе представлены функции, которые делают Scala масштабируемым языком. Эти функции разделены на три раздела:
- Функции высокоуровневого языка программирования
 - Функции низкоуровневого языка программирования
 - Особенности экосистемы Scala
 
Высокоуровневые функции
Глядя на Scala с пресловутого “вида с высоты 30 000 фунтов”, вы можете сделать о нем следующие утверждения:
- Это высокоуровневый язык программирования
 - Он имеет краткий, читаемый синтаксис
 - Он статически типизирован (но кажется динамичным)
 - Имеет выразительную систему типов
 - Это язык функционального программирования (ФП)
 - Это язык объектно-ориентированного программирования (ООП)
 - Он поддерживает слияние ФП и ООП
 - Контекстные абстракции обеспечивают понятный способ реализации вывода терминов (term inference)
 - Он работает на JVM (и в браузере)
 - Беспрепятственно взаимодействует с Java кодом
 - Он используется для серверных приложений (включая микросервисы), приложений для работы с большими данными, а также может использоваться в браузере с помощью Scala.js
 
Эти функции кратко рассматриваются в следующих разделах.
Высокоуровневый язык
Scala считается высокоуровневым языком как минимум по двум причинам. Во-первых, подобно Java и многим другим современным языкам, вы не имеете дело с низкоуровневыми понятиями, такими как указатели и управление памятью.
Во-вторых, с использованием лямбда-выражений и функций высшего порядка вы пишете свой код на очень высоком уровне. Как говорится в функциональном программировании, в Scala вы пишете то, что хотите, а не то, как этого добиться. То есть мы не пишем императивный код вот так:
import scala.collection.mutable.ListBuffer
def double(ints: List[Int]): List[Int] = {
  val buffer = new ListBuffer[Int]()
  for (i <- ints) {
    buffer += i * 2
  }
  buffer.toList
}
val oldNumbers = List(1, 2, 3)
val newNumbers = double(oldNumbers)
import scala.collection.mutable.ListBuffer
def double(ints: List[Int]): List[Int] =
  val buffer = new ListBuffer[Int]()
  for i <- ints do
    buffer += i * 2
  buffer.toList
val oldNumbers = List(1, 2, 3)
val newNumbers = double(oldNumbers)
Этот код шаг за шагом указывает компилятору, что делать. Вместо этого мы пишем высокоуровневый функциональный код, используя функции высшего порядка и лямбда-выражения, подобные этому, для вычисления того же результата:
val newNumbers = oldNumbers.map(_ * 2)
Как видите, этот код намного лаконичнее, его легче читать и легче поддерживать.
Лаконичный синтаксис
Scala имеет краткий, удобочитаемый синтаксис. Например, переменные создаются лаконично, а их типы понятны:
val nums = List(1,2,3)
val p = Person("Martin", "Odersky")
Функции высшего порядка и лямбда-выражения делают код кратким и удобочитаемым:
nums.map(i => i * 2)   // длинная форма
nums.map(_ * 2)        // краткая форма
nums.filter(i => i > 1)
nums.filter(_ > 1)
Трэйты, классы и методы определяются с помощью простого и легкого синтаксиса:
trait Animal {
  def speak(): Unit
}
trait HasTail {
  def wagTail(): Unit
}
class Dog extends Animal with HasTail {
  def speak(): Unit = println("Woof")
  def wagTail(): Unit = println("⎞⎜⎛  ⎞⎜⎛")
}
trait Animal:
  def speak(): Unit
trait HasTail:
  def wagTail(): Unit
class Dog extends Animal, HasTail:
  def speak(): Unit = println("Woof")
  def wagTail(): Unit = println("⎞⎜⎛  ⎞⎜⎛")
Исследования показали, что время, которое разработчик тратит на чтение и написание кода, составляет как минимум 10:1, поэтому важно писать краткий и читабельный код.
Ощущение динамики
Scala — это язык со статической типизацией, но благодаря своим возможностям вывода типов он кажется динамичным. Все эти выражения выглядят как языки с динамической типизацией, такие как Python или Ruby, но это все Scala:
val s = "Hello"
val p = Person("Al", "Pacino")
val sum = nums.reduceLeft(_ + _)
val y = for (i <- nums) yield i * 2
val z = nums
  .filter(_ > 100)
  .filter(_ < 10_000)
  .map(_ * 2)
val s = "Hello"
val p = Person("Al", "Pacino")
val sum = nums.reduceLeft(_ + _)
val y = for i <- nums yield i * 2
val z = nums
  .filter(_ > 100)
  .filter(_ < 10_000)
  .map(_ * 2)
Как утверждает Heather Miller, Scala считается сильным языком со статической типизацией, и вы получаете все преимущества статических типов:
- Корректность: вы обнаруживаете большинство ошибок во время компиляции
 - Отличная поддержка IDE
    
- Надежное автодополнение кода
 - Отлов ошибок во время компиляции означает отлов ошибок по мере написания
 - Простой и надежный рефакторинг
 
 - Вы можете уверенно рефакторить свой код
 - Объявления типов методов сообщают читателям, что делает метод, и помогают служить документацией
 - Масштабируемость и удобство обслуживания: типы помогают обеспечить корректность в произвольно больших приложениях и командах разработчиков
 - Строгая типизация в сочетании с превосходным выводом типов позволяет использовать такие механизмы, как контекстная абстракция, которая позволяет вам опускать шаблонный код. Часто этот шаблонный код может быть выведен компилятором на основе определений типов и заданного контекста.
 
Выразительная система типов
Система типов в Scala во время компиляции обеспечивает безопасное и согласованное использование абстракций. В частности, система типов поддерживает:
- Выводимые типы
 - Generic классы
 - Аннотации вариантности
 - Верхняя и нижняя границы типов
 - Полиморфные методы
 - Типы пересечения
 - Типы объединения
 - Лямбда-типы
 - Экземпляры 
givenи предложенияusing - Методы расширения
 - Типовые классы
 - Многостороннее равенство
 - Псевдонимы непрозрачного типа
 - Открытые классы
 - Типы соответствия
 - Зависимые типы функций
 - Полиморфные функциональные типы
 - Контекстные границы
 - Контекстные функции
 - Внутренние классы и элементы абстрактного типа как элементы объекта
 
В сочетании эти функции обеспечивают мощную основу для безопасного повторного использования программных абстракций и для безопасного расширения программного обеспечения.
Язык функционального программирования
Scala — это язык функционального программирования (ФП), что означает:
- Функции — это значения, и их можно передавать, как и любое другое значение
 - Напрямую поддерживаются функции высшего порядка
 - Встроенные лямбда
 - Все в Scala — это выражение, возвращающее значение
 - Синтаксически легко использовать неизменяемые переменные, и их использование приветствуется
 - В стандартной библиотеке языка содержится множество неизменяемых классов коллекций
 - Эти классы коллекций поставляются с десятками функциональных методов: они не изменяют коллекцию, вместо этого возвращая обновленную копию данных
 
Объектно-ориентированный язык
Scala — это язык объектно-ориентированного программирования (ООП). Каждое значение — это экземпляр класса, а каждый “оператор” — это метод.
В Scala все типы наследуются от класса верхнего уровня Any, чьими непосредственными дочерними элементами являются AnyVal (типы значений, такие как Int и Boolean) и AnyRef (ссылочные типы, как в Java).
Это означает, что различие в Java между примитивными и упакованными типами (например, int против Integer) отсутствует в Scala. 
Упаковка и распаковка полностью прозрачны для пользователя.
Поддерживает слияние ФП/ООП
Суть Scala заключается в слиянии функционального программирования и объектно-ориентированного программирования в типизированной среде:
- Функции для логики
 - Объекты для модульности
 
Как заявил Мартин Одерски, “Scala был разработан, чтобы показать, что слияние функционального и объектно-ориентированного программирования возможно и практично”.
Вывод терминов стал более понятным
После Haskell Scala был вторым популярным языком, в котором была некоторая форма неявных (implicits) выражений. В Scala 3 эти концепции были полностью переосмыслены и реализованы более четко.
Основная идея заключается в выводе терминов: на основе заданного, компилятор синтезирует “канонический” термин, который имеет этот тип. В Scala параметр контекста напрямую ведет к выводимому термину аргумента, который также может быть записан явно.
Примеры использования этой концепции включают реализацию типовых классов, установление контекста, внедрение зависимостей, выражение возможностей, вычисление новых типов и доказательство отношений между ними.
Scala 3 делает этот процесс более понятным, чем когда-либо прежде. О контекстных абстракциях можно прочесть в Справочной документации.
Клиент & сервер
Код Scala работает на виртуальной машине Java (JVM), поэтому вы получаете все ее преимущества:
- Безопасность
 - Производительность
 - Управление памятью
 - Портативность и независимость от платформы
 - Возможность использовать множество существующих Java и JVM библиотек
 
Помимо работы на JVM, Scala также работает в браузере с помощью Scala.js (и сторонних инструментов с открытым исходным кодом для интеграции популярных библиотек JavaScript), а собственные исполняемые файлы могут быть созданы с помощью Scala Native и GraalVM.
Беспрепятственное взаимодействие с Java
Вы можете использовать Java классы и библиотеки в своих приложениях Scala, а также код Scala в приложениях Java. Что касается второго пункта, большие библиотеки, такие как Akka и Play Framework написаны на Scala и могут использоваться в приложениях Java.
Что касается первого пункта, классы и библиотеки Java используются в приложениях Scala каждый день.
Например, в Scala вы можете читать файлы с помощью BufferedReader и FileReader из Java:
import java.io.*
val br = BufferedReader(FileReader(filename))
// чтение файла в `br` ...
Использование Java-кода в Scala, как правило, не вызывает затруднений.
В Scala также можно использовать коллекции Java, и если вы хотите использовать с ними богатый набор методов классов коллекций Scala, то можете преобразовать их с помощью всего нескольких строк кода:
import scala.jdk.CollectionConverters.*
val scalaList: Seq[Integer] = JavaClass.getJavaList().asScala.toSeq
Богатство библиотек
Как будет видно в третьем разделе этой страницы, библиотеки и фреймворки Scala, подобные нижеследующим, были написаны для поддержки загруженных веб-сайтов и работы с огромными наборами данных:
- Play Framework — это легкая, без сохранения состояния, удобная для web, удобная для разработчиков архитектура для создания масштабируемых приложений
 - Apache Spark — это унифицированный аналитический механизм для обработки больших данных со встроенными модулями для потоковой передачи, SQL, машинного обучения и обработки графиков
 
В списке Awesome Scala представлены десятки дополнительных инструментов с открытым исходным кодом, созданных разработчиками для создания приложений Scala.
В дополнение к программированию на стороне сервера, Scala.js представляет собой строго типизированную замену для написания JavaScript со сторонними библиотеками с открытым исходным кодом, которые включают инструменты для интеграции с библиотекой Facebook React, jQuery и т.д.
Функции низкоуровневого языка
Хотя в предыдущем разделе были рассмотрены высокоуровневые функции Scala, интересно отметить, что на высоком уровне вы можете делать одни и те же утверждения как о Scala 2, так и о Scala 3. Десять лет назад Scala начиналась с прочного фундамента желаемых функций, и вы увидите в этом разделе, что в Scala 3 эти преимущества были улучшены.
С точки зрения деталей “на уровне моря” — то есть функций языка, которые программисты используют каждый день — Scala 3 имеет значительные преимущества по сравнению со Scala 2:
- Возможность более лаконично создавать алгебраические типы данных (ADT) с перечислениями
 - Еще более лаконичный и читаемый синтаксис:
    
- Синтаксис “тихой” структуры управления легче читать
 - Опциональные фигурные скобки
        
- Меньшее количество символов в коде создает меньше визуального шума, что упрощает его чтение
 
 - Ключевое слово 
newобычно больше не требуется при создании экземпляров класса - Формальность объектов пакета была заменена более простыми определениями “верхнего уровня”
 
 - Более понятная грамматика:
    
- Несколько различных вариантов использования ключевого слова 
implicitбыли удалены; это использование заменено более очевидными ключевыми словами, такими какgiven,using, иextension, фокусирующихся на намерении, а не механизме (подробности см. в разделе Givens) - Методы расширения заменяют неявные классы более понятным и простым механизмом
 - Добавление модификатора 
openдля классов заставляет разработчика намеренно объявить, что класс открыт для модификации, тем самым ограничивая специальные расширения кодовой базы - Многостороннее равенство исключает бессмысленные сравнения с 
==и!=(т.е. попытки сравнитьPersonсPlanet) - Гораздо проще реализуются макросы
 - Объединение и пересечение предлагают гибкий способ моделирования типов
 - Параметры трейтов заменяют и упрощают ранние инициализаторы
 - Псевдонимы непрозрачных типов заменяют большинство случаев использования классов значений, гарантируя при этом отсутствие упаковки
 - Export предложения обеспечивают простой и общий способ выражения агрегации, который может заменить предыдущий шаблон фасада объектов пакета, наследуемых от классов
 - Синтаксис procedure был удален, а синтаксис varargs - изменен, чтобы сделать язык более согласованным
 @infixаннотация делает очевидным желаемое применение метода- Аннотация метода 
@targetNameопределяет альтернативное имя метода, улучшая совместимость с Java и позволяя указывать псевдонимы для символических операторов 
 - Несколько различных вариантов использования ключевого слова 
 
Демонстрация всех этих функций заняла бы слишком много места, но перейдите по ссылкам в пунктах выше, чтобы увидеть эти функции в действии. Все эти функции подробно обсуждаются на страницах New, Changed и Dropped функций в обзорной документации.
Экосистема Scala
У Scala динамичная экосистема с библиотеками и фреймворками под любые требования. Список “Awesome Scala” содержит список сотен проектов с открытым исходным кодом, доступных разработчикам Scala, а Scaladex предоставляет доступный для поиска индекс библиотек Scala. Некоторые из наиболее известных библиотек перечислены ниже.
Web разработка
- Play Framework следует модели Ruby on Rails, чтобы стать легкой, не сохраняющей состояния, удобной для разработчиков и web архитектурой для высокомасштабируемых приложений
 - Scalatra — небольшой высокопроизводительный асинхронный web framework, вдохновленный Sinatra
 - Finatra — это сервисы Scala, построенные на TwitterServer и Finagle
 - Scala.js — это строго типизированная замена JavaScript, обеспечивающая более безопасный способ создания надежных интерфейсных web-приложений
 - ScalaJs-React поднимает библиотеку Facebook React на Scala.js и пытается сделать ее максимально безопасной для типов и удобной для Scala
 
HTTP(S) библиотеки:
JSON библиотеки:
Сериализация:
Наука и анализ данных:
Большие данные
ИИ, машинное обучение
- BigDL (Распределенная среда глубокого обучения для Apache Spark)
 - TensorFlow Scala
 
Функциональное программирование & Функциональное реактивное программирование
ФП:
Функциональное реактивное программирование (ФРП):
Инструменты сборки
Подведем итоги
Как показано на этой странице, Scala обладает множеством замечательных функций высокоуровневого языка программирования, низкоуровневого языка программирования и богатой экосистемой разработчиков.
Contributors to this page:
Contents
- Введение
 - Возможности Scala
 - Почему Scala 3?
 - Почувствуй Scala
 - Пример 'Hello, World!'
 - REPL
 - Переменные и типы данных
 - Структуры управления
 - Моделирование данных
 - Методы
 - Функции первого класса
 - Одноэлементные объекты
 - Коллекции
 - Контекстные абстракции
 - Верхнеуровневые определения
 - Обзор
 - Первый взгляд на типы
 - Интерполяция строк
 - Структуры управления
 - Моделирование предметной области
 - Инструменты
 - Моделирование ООП
 - Моделирование ФП
 - Методы
 - Особенности методов
 - Main методы в Scala 3
 - Обзор
 - Функции
 - Анонимные функции
 - Параметры функции
 - Eta расширение
 - Функции высшего порядка
 - Собственный map
 - Создание метода, возвращающего функцию
 - Обзор
 - Пакеты и импорт
 - Коллекции в Scala
 - Типы коллекций
 - Методы в коллекциях
 - Обзор
 - Функциональное программирование
 - Что такое функциональное программирование?
 - Неизменяемые значения
 - Чистые функции
 - Функции — это значения
 - Функциональная обработка ошибок
 - Обзор
 - Типы и система типов
 - Определение типов
 - Параметризованные типы
 - Пересечение типов
 - Объединение типов
 - Алгебраические типы данных
 - Вариантность
 - Непрозрачные типы
 - Структурные типы
 - Зависимые типы функций
 - Другие типы
 - Контекстные абстракции
 - Методы расширения
 - Параметры контекста
 - Контекстные границы
 - Given импорты
 - Классы типов
 - Многостороннее равенство
 - Неявное преобразование типов
 - Обзор
 - Параллелизм
 - Scala утилиты
 - Сборка и тестирование проектов Scala с помощью Sbt
 - Рабочие листы
 - Взаимодействие с Java