«Scala. Профессиональное программирование» — главная книга по Scala, популярному языку для платформы Java, в котором сочетаются концепции объектно-ориентированного и функционального программирования, благодаря чему он превращается в уникальное и мощное средство разработки. Этот авторитетный труд, написанный создателями Scala, поможет вам пошагово изучить язык и идеи, лежащие в его основе. Пятое издание значительно обновлено, чтобы охватить многочисленные изменения, появившиеся в Scala 3. Отзывы на предыдущие издания книги Предисловие Благодарности Введение Целевая аудитория Как пользоваться книгой Как изучать Scala Условные обозначения Структура книги Ресурсы Исходный код От издательства Глава 1. Масштабируемый язык 1.1. Язык, который растет вместе с вами Растут новые типы Растут новые управляющие конструкции 1.2. Почему язык Scala масштабируемый? Scala — объектно-ориентированный язык Scala — функциональный язык 1.3. Почему именно Scala Scala — совместимый язык Scala — лаконичный язык Scala — высокоуровневый язык Scala — статически типизированный язык 1.4. Истоки Scala Резюме Глава 2. Первые шаги в Scala Шаг 1. Осваиваем Scala REPL Шаг 2. Объявляем переменные Шаг 3. Определяем функции Шаг 4. Пишем Scala-скрипты Шаг 5. Организуем цикл с while и принимаем решение с if Шаг 6. Перебираем элементы с foreach и for-do Резюме Глава 3. Дальнейшие шаги в Scala Шаг 7. Параметризуем массивы типами Шаг 8. Используем списки Шаг 9. Используем кортежи Шаг 10. Используем множества и отображения Шаг 11. Учимся распознавать функциональный стиль Шаг 12. Преобразование с отображениями и for-yield Резюме Глава 4. Классы и объекты 4.1. Классы, поля и методы 4.2. Когда подразумевается использование точки с запятой 4.3. Объекты-одиночки 4.4. Case-классы 4.5. Приложение на языке Scala Резюме Глава 5. Основные типы и операции 5.1. Некоторые основные типы 5.2. Литералы Целочисленные литералы Литералы чисел с плавающей точкой Большие числовые литералы Символьные литералы Строковые литералы Булевы литералы 5.3. Интерполяция строк 5.4. Все операторы являются методами 5.5. Арифметические операции 5.6. Отношения и логические операции 5.7. Поразрядные операции 5.8. Равенство объектов 5.9. Приоритет и ассоциативность операторов 5.10. Обогащающие операции Резюме Глава 6. Функциональные объекты 6.1. Спецификация класса Rational 6.2. Конструирование класса Rational 6.3. Переопределение метода toString 6.4. Проверка соблюдения предварительных условий 6.5. Добавление полей 6.6. Собственные ссылки 6.7. Вспомогательные конструкторы 6.8. Приватные поля и методы 6.9. Определение операторов 6.10. Идентификаторы в Scala 6.11. Перегрузка методов 6.12. Методы расширения 6.13. Предостережение Резюме Глава 7. Встроенные управляющие конструкции 7.1. Выражения if 7.2. Циклы while 7.3. Выражения for Обход элементов коллекций Фильтрация Вложенные итерации Привязки промежуточных переменных Создание новой коллекции 7.4. Обработка исключений с помощью выражений try Генерация исключений Перехват исключений Условие finally Выдача значения 7.5. Выражения match 7.6. Программирование без break и continue 7.7. Область видимости переменных 7.8. Рефакторинг кода, написанного в императивном стиле 7.9. Резюме Глава 8. Функции и замыкания 8.1. Методы 8.2. Локальные функции 8.3. Функции первого класса 8.4. Краткие формы функциональных литералов 8.5. Синтаксис заместителя 8.6. Частично примененные функции 8.7. Замыкания 8.8. Специальные формы вызова функций Повторяющиеся параметры Именованные аргументы Значения параметров по умолчанию 8.9. Тип SAM 8.10. Хвостовая рекурсия Трассировка функций с хвостовой рекурсией Ограничения хвостовой рекурсии Резюме Глава 9. Управляющие абстракции 9.1. Сокращение повторяемости кода 9.2. Упрощение клиентского кода 9.3. Карринг 9.4. Создание новых управляющих конструкций 9.5. Передача параметров по имени Резюме Глава 10. Композиция и наследование 10.1. Библиотека двумерной разметки 10.2. Абстрактные классы 10.3. Определяем методы без параметров 10.4. Расширяем классы 10.5. Переопределяем методы и поля 10.6. Определяем параметрические поля 10.7. Вызываем конструктор суперкласса 10.8. Используем модификатор override 10.9. Полиморфизм и динамическое связывание 10.10. Объявляем финальные элементы 10.11. Используем композицию и наследование 10.12. Реализуем методы above, beside и toString 10.13. Определяем фабричный объект 10.14. Методы heighten и widen 10.15. Собираем все вместе Резюме Глава 11. Трейты 11.1. Как работают трейты 11.2. Сравнение «тонких» и «толстых» интерфейсов 11.3. Трейты как наращиваемые модификации 11.4. Почему не используется множественное наследование 11.5. Параметры трейтов Резюме Глава 12. Пакеты, импорты и экспорты 12.1. Помещение кода в пакеты 12.2. Краткая форма доступа к родственному коду 12.3. Импортирование кода 12.4. Неявное импортирование 12.5. Модификаторы доступа Приватные члены Защищенные члены Публичные члены Область защиты Видимость и объекты-компаньоны 12.6. Определения верхнего уровня 12.7. Экспорты Резюме Глава 13. Сопоставление с образцом 13.1. Простой пример Case-классы Сопоставление с образцом Сравнение match со switch 13.2. Разновидности паттернов Подстановочные паттерны Паттерны-константы Патерны-переменные Паттерны-конструкторы Паттерны-последовательности Паттерны-кортежи Типизированные паттерны Затирание типов Привязка переменной 13.3. Ограждение образца 13.4. Наложение паттернов 13.5. Запечатанные классы 13.6. Сопоставление паттерна Options 13.7. Паттерны повсюду Паттерны в определениях переменных Последовательности вариантов в качестве частично примененных функций Паттерны в выражениях for 13.8. Большой пример Резюме Глава 14. Работа со списками 14.1. Литералы списков 14.2. Тип List 14.3. Создание списков 14.4. Основные операции над списками 14.5. Паттерны-списки 14.6. Методы первого порядка класса List Конкатенация двух списков Принцип «разделяй и властвуй» Получение длины списка: length Обращение к концу списка: init и last Реверсирование списков: reverse Префиксы и суффиксы: drop, take и splitAt Выбор элемента: apply и indices Линеаризация списка списков: flatten Объединение списков: zip и unzip Отображение списков: toString и mkString Преобразование списков: iterator, toArray, copyToArray Пример: сортировка слиянием 14.7. Методы высшего порядка класса List Отображения списков: map, flatMap и foreach Фильтрация списков: filter, partition, find, takeWhile, dropWhile и span Применение предикатов к спискам: forall и exists Свертка списков: foldLeft и foldRight Пример: реверсирование списков с помощью свертки Сортировка списков: sortWith 14.8. Методы объекта List Создание списков из их элементов: List.apply Создание диапазона чисел: List.range Создание единообразных списков: List.fill Табулирование функции: List.tabulate Конкатенация нескольких списков: List.concat 14.9. Совместная обработка нескольких списков 14.10. Понимание имеющегося в Scala алгоритма вывода типов Резюме Глава 15. Работа с другими коллекциями 15.1. Последовательности Списки Массивы Буферы списков Буферы массивов Строки (реализуемые через StringOps) 15.2. Множества и отображения Использование множеств Применение отображений Множества и отображения, используемые по умолчанию Отсортированные множества и отображения 15.3. Выбор между изменяемыми или неизменяемыми коллекциями 15.4. Инициализация коллекций Преобразование в массив или список Преобразования между изменяемыми и неизменяемыми множествами и отображениями 15.5. Кортежи Резюме Глава 16. Изменяемые объекты 16.1. Что делает объект изменяемым 16.2. Переназначаемые переменные и свойства 16.3. Практический пример: моделирование дискретных событий 16.4. Язык для цифровых схем 16.5. API моделирования 16.6. Моделирование электронной логической схемы Класс Wire Метод inverter Методы andGate и orGate Вывод симуляции Запуск симулятора Резюме Глава 17. Иерархия Scala 17.1. Иерархия классов Scala 17.2. Как реализованы примитивы 17.3. Низшие типы 17.4. Определение собственных классов значений Уход от монокультурности типов 17.5. Типы пересечений 17.6. Типы объединения 17.7. Прозрачные трейты Резюме Глава 18. Параметризация типов 18.1. Функциональные очереди 18.2. Сокрытие информации Приватные конструкторы и фабричные методы Альтернативный вариант: приватные классы 18.3. Аннотации вариантности Вариантность и массивы 18.4. Проверка аннотаций вариантности 18.5. Нижние ограничители 18.6. Контравариантность 18.7. Верхние ограничители Резюме Глава 19. Перечисления 19.1. Перечисляемые типы данных 19.2. Алгебраические типы данных 19.3. Обобщенные ADT 19.4. Что делает типы ADT алгебраическими Резюме Глава 20. Абстрактные члены 20.1. Краткий обзор абстрактных членов 20.2. Члены-типы 20.3. Абстрактные val-переменные 20.4. Абстрактные var-переменные 20.5. Инициализация абстрактных val-переменных Параметрические поля трейтов Ленивые val-переменные 20.6. Абстрактные типы 20.7. Типы, зависящие от пути 20.8. Уточняющие типы 20.9. Практический пример: работа с валютой Резюме Глава 21. Гивенсы 21.1. Как это работает 21.2. Параметризованные заданные типы 21.3. Анонимные заданные экземпляры 21.4. Параметризованные заданные экземпляры в виде классов типов 21.5. Импорт заданных экземпляров 21.6. Правила для контекстных параметров 21.7. Когда подходит сразу несколько заданных экземпляров 21.8. Отладка заданных экземпляров Резюме Глава 22. Методы расширения 22.1. Основы 22.2. Обобщенные расширения 22.3. Групповые расширения 22.4. Использование класса типов 22.5. Методы расширения для заданных экземпляров 22.6. Где Scala ищет методы расширения Резюме Глава 23. Классы типов 23.1. Зачем нужны классы типов 23.2. Границы контекста 23.3. Главные методы 23.4. Многостороннее равенство 23.5. Неявные преобразования 23.6. Пример использования класса типов: сериализация JSON Резюме Глава 24. Углубленное изучение коллекций 24.1. Изменяемые и неизменяемые коллекции 24.2. Согласованность коллекций 24.3. Трейт Iterable Подкатегории Iterable 24.4. Трейты последовательностей Seq, IndexedSeq и LinearSeq Буферы 24.5. Множества 24.6. Отображения 24.7. Конкретные классы неизменяемых коллекций Списки Ленивые списки Неизменяемые ArraySeq Векторы Неизменяемые очереди Диапазоны Сжатые коллекции HAMT Красно-черные деревья Неизменяемые битовые множества Векторные отображения Списочные отображения 24.8. Конкретные классы изменяемых коллекций Буферы массивов Буферы списков Построители строк ArrayDeque Очереди Стеки Изменяемые ArraySeq Хеш-таблицы Слабые хеш-отображения Совместно используемые отображения Изменяемые битовые множества 24.9. Массивы 24.10. Строки 24.11. Характеристики производительности 24.12. Равенство 24.13. Представления 24.14. Итераторы Буферизированные итераторы 24.15. Создание коллекций с нуля 24.16. Преобразования между коллекциями Java и Scala Резюме Глава 25. Утверждения и тесты 25.1. Утверждения 25.2. Тестирование в Scala 25.3. Информативные отчеты об ошибках 25.4. Использование тестов в качестве спецификаций 25.5. Тестирование на основе свойств 25.6. Подготовка и проведение тестов Резюме Глоссарий Библиография Об авторах