Грокаем функциональное программирование

This document was uploaded by one of our users. The uploader already confirmed that they had the permission to publish it. If you are author/publisher or own the copyright of this documents, please report to us by using this DMCA report form.

Simply click on the Download Book button.

Yes, Book downloads on Ebookily are 100% Free.

Sometimes the book is free on Amazon As well, so go ahead and hit "Search on Amazon"

Вам кажется, что функциональное программирование – это нечто сложное, доступное только гуру программирования? Эта книга развенчает миф об элитарности и позволит любому программисту с легкостью разобраться в хитросплетениях кода. От знакомых и простых идей ООП вы перейдете к ФП, рассматривая его на простых примерах, захватывающих упражнениях и большом количестве иллюстраций. Вы начнете с решения простых и маленьких задач, иллюстрирующих базовые понятия, такие как чистые функции и неизменяемые данные, научитесь писать код, лишенный типичных ошибок, обусловленных наличием сложного распределенного состояния, разберетесь с подходами к реализации ввода-вывода, параллельного выполнения и потоковой передачи данных. К концу книги вы будете создавать ясный функциональный код, который легко читается, тестируется и сопровождается. https://github.com/miciek/grokkingfp-examples

Author(s): Михал Плахта
Series: Библиотека программиста
Publisher: Питер
Year: 2024

Language: Russian
Pages: 512
City: СПб.

Оглавление
Предисловие
Благодарности
Об этой книге
Кому адресована книга
Структура издания
О примерах программного кода
Об авторе
От издательства
Часть I. Функциональный инструментарий
1. Изучение функционального программирования
Возможно, вы купили эту книгу потому, что...
Что нужно знать перед тем, как начать
Как выглядят функции
Зачем все эти public static
Короткое упражнение
Встречайте: функция
Сигнатура и тело
Короткое упражнение
Когда код лжет...
Императивный и декларативный стили
Императивный подсчет баллов
Декларативный подсчет баллов
Перерыв на кофе: императивный и декларативный стили
Объяснение для перерыва на кофе: императивный и декларативный стили
Императивное решение
Декларативное решение
Насколько полезно изучать функциональное программирование
Стиль написания кода на любом языке
Функциональные концепции одинаковы в языках ФП
Функциональное и декларативное мышление
Прыжок в Scala
Практика функций в Scala
Подготовка инструментов
Знакомство с REPL
Пишем свои первые функции!
Как использовать эту книгу
Резюме
Кому адресована эта книга
Что такое функция
Насколько полезно функциональное программирование
Установка необходимых инструментов
Как пользоваться этой книгой
2. Чистые функции
Зачем нужны чистые функции
Императивное решение
Ошибка в коде
Передача копий данных
Ошибка в коде... снова
Повторные вычисления вместо сохранения
Сосредоточение внимания на логике путем передачи состояния
Куда пропало состояние
Разделение ответственности
Разница между чистыми и нечистыми функциями
Перерыв на кофе: преобразование в чистую функцию
Объяснение для перерыва на кофе: преобразование в чистую функцию
Повторные вычисления вместо сохранения
Передача состояния в качестве аргумента
Передача копий данных
Мы доверяем чистым функциям
Математические функции — чистые
Чистые функции в языках программирования
Трудно оставаться чистым...
Чистые функции и чистый код
Перерыв на кофе: чистая или нечистая
Объяснение для перерыва на кофе: чистая или нечистая
Использование Scala для написания чистых функций
Практика чистых функций в Scala
Тестирование чистых функций
Перерыв на кофе: тестирование чистых функций
Объяснение для перерыва на кофе: тестирование чистых функций
Резюме
Зачем нужны чистые функции
Передача копий данных
Повторные вычисления вместо сохранения
Передача состояния
Тестирование чистых функций
3. Неизменяемые значения
Топливо для двигателя
Еще один пример неизменяемости
Можно ли доверять этой функции
Изменяемость опасна
Функции, которые лгут... снова
Борьба с изменяемостью за счет использования копий
Изменение значений внутри чистой функции
Перерыв на кофе: обжигаемся на изменяемости
Объяснение для перерыва на кофе: обжигаемся на изменяемости
Отладка totalTime
Отладка avgTime
Отладка totalTime и avgTime в комплексе
Делаем функции чистыми, используя копии
Можно ли улучшить решение
Знакомьтесь: общее изменяемое состояние
Что такое общее изменяемое состояние
Влияние состояния на возможность программирования
Работа с движущимися частями
Объектно-ориентированный подход
Работа с движущимися частями в ФП
Функциональный подход
Краткий обзор функционального подхода в Scala
Неизменяемые значения в Scala
Проверка List в Scala REPL
Вырабатываем интуитивное понимание неизменности
Перерыв на кофе: неизменяемый тип String
Объяснение для перерыва на кофе: неизменяемый тип String
Постойте... Разве это не плохо?
Чисто функциональный подход к общему изменяемому состоянию
Концентрация внимания на отношениях между значениями
Преобразование отношений в выражения
Включение выражений в тело функции
Практика работы с неизменяемыми списками
Резюме
Изменяемость опасна
Борьба с изменяемостью с помощью копий
Что такое общее изменяемое состояние
Борьба с изменяемостью с помощью неизменяемых значений
Использование неизменяемых строк String и списков List
4. Функции как значения
Реализация требований в виде функций
Оценка слов
Нечистые функции и изменяемые значения наносят ответный удар
Версия 1: с использованием функций Comparator и sort
Использование Java Streams для сортировки списка
Версия 2: ранжирование слов с использованием Streams
Сигнатуры функций должны рассказывать всю правду
Версия 3: передача алгоритмов в аргументах
Изменение требований
Версия 4: изменение алгоритма ранжирования
Мы можем передавать код в аргументах!
Использование значений Function в Java
Использование синтаксиса Function для устранения повторяющегося кода
Передача пользовательских функций в виде аргументов
Версия 5: передача функции оценки
Перерыв на кофе: функции как параметры
Упражнение: реализуйте новое требование
Объяснение для перерыва на кофе: функции как параметры
Проблемы с чтением функционального кода на Java
Слишком много кода
Мы по-прежнему используем изменяемые списки
Передача функций в Scala
Глубокое погружение в sortBy
Сигнатуры с параметрами-функциями в Scala
Сигнатура
Передача функций в виде аргументов в Scala
Первая попытка: использование sortBy
Практика передачи функций
Использование декларативного программирования
Ранжирование слов хакерским способом
Декларативное ранжирование слов
Передача функций пользовательским функциям
Маленькие функции и их обязанности
Оптимизация для удобочитаемости
Что не так с функцией scoreWithBonus
Передача встроенных функций
Перерыв на кофе: передача функций в Scala
Объяснение для перерыва на кофе: передача функций в Scala
Использование RankedWords с функцией score
Использование rankedWords c функциями score и bonus
Реализация нового требования
Использование rankedWords с функциями score, bonus и penalty
Чего еще можно добиться, просто передавая функции
Применение функции к каждому элементу списка
Для справки: императивное решение на Java
Для справки: решение на Java с использованием Streams
Применение функции к каждому элементу списка с помощью map
Сигнатура
Тело
Знакомство с map
Использование карты на практике
Практика map
Изучите однажды, используйте постоянно
Чего еще можно добиться, передавая функции
Возврат части списка, соответствующей условию
Короткое упражнение: сигнатура
Для справки: императивное решение на Java
Сигнатура на Scala
Возврат части списка с помощью filter
Сигнатура
Тело
Знакомство с filter
Использование filter на практике
Практика filter
Насколько далеко мы зашли в нашем путешествии...
Не повторяйся?
Легко ли использовать мой API
Добавления нового параметра недостаточно
Функции могут возвращать функции
Сигнатура
Тело
Использование функций, возвращающих функции
Функции — это значения
Перерыв на кофе: возврат функций
Объяснение для перерыва на кофе: возврат функций
Проектирование функциональных API
Итеративный дизайн функциональных API
Возврат функций из возвращаемых функций
Как вернуть функцию из возвращаемой функции
Использование гибкого API, построенного с использованием возвращаемых функций
Использование нескольких списков параметров в функциях
Проблема: непоследовательность в именовании параметров
Решение: несколько списков параметров
У нас есть карринг!
Практика каррирования
Программирование с передачей функций в виде значений
Свертка множества значений в одно
Для справки: императивное решение на Java
Сигнатура на Scala
Свертка множества значений в одно с помощью foldLeft
Сигнатура
Тело
Знакомство с foldLeft
Каждый должен знать и уметь пользоваться foldLeft
Почему в имени присутствует слово left
Практика foldLeft
Моделирование неизменяемых данных
Соединение двух частей информации вместе
Использование типов-произведений с функциями высшего порядка
Типы-произведения — неизменяемые
Получение списка имен с помощью map
Выбор наиболее молодых языков с помощью filter
Более лаконичный синтаксис встроенных функций
Использование map и filter с синтаксисом подчеркивания
Резюме
Передача функций в параметрах
Функция sortBy
Функции map и filter
Возврат функций из функций
Функция foldLeft
Моделирование неизменяемых данных с использованием типа-произведения
Часть II. Функциональные программы
5. Последовательные программы
Написание конвейерных алгоритмов
Составление больших программ из мелких деталей
Императивный подход
flatten и flatMap
Практические примеры использования flatMap
flatMap и изменение размера списка
Перерыв на кофе: работа со списками списков
Объяснение для перерыва на кофе: работа со списками списков
Объединение в цепочку вызовов flatMap и map
Вложенные вызовы flatMap
Значения, зависящие от других значений
Практика использования вложенных вызовов flatMap
Улучшенный синтаксис вложенных вызовов flatMap
for-выражения во спасение!
Перерыв на кофе: flatMap и for-выражение
Объяснение перерыва на кофе: flatMap и for-выражение
Знакомство с for-выражениями
Это не тот for, который вы знаете!
Внутреннее устройство for-выражения
Более сложные for-выражения
Находится ли точка внутри данного круга
Проверка всех комбинаций с помощью for-выражения
Фильтрация внутри for-выражения
Приемы фильтрации
Использование filter
Использование ограничительного выражения (if в for-выражениях)
Передача функции в вызов flatMap
Перерыв на кофе: методы фильтрации
Отфильтруйте недопустимые радиусы
Объяснение для перерыва на кофе: методы фильтрации
В поисках большей абстракции
Сравнение map, foldLeft и flatMap
Использование for-выражений с множествами Set
Использование Set внутри for-выражения
Использование for-выражений с данными нескольких типов
Практика for-выражений
Определение for-выражения... снова
Использование for-выражений с типами, не являющимися коллекциями
Парсинг исторических событий
Прямолинейное решение
Избегайте значений null: тип Option
Значения null заставляют наши сигнатуры лгать
Тип Option
Парсинг в виде конвейера
Перерыв на кофе: парсинг с Option
Объяснение перерыва на кофе: парсинг с Option
Резюме
Обрабатывали списки списков с помощью flatten
Писали последовательные программы, используя flatMap вместо циклов for
Писали удобочитаемые последовательные программы, используя for-выражения
Использовали условия внутри for-выражений
Познакомились с некоторыми другими типами, поддерживающими flatMap
6. Обработка ошибок
Изящная обработка множества различных ошибок
Движок парсинга телесериалов
Что вы узнаете в этой главе
Возможно ли вообще справиться со всеми ними
Сортировка списка телесериалов по продолжительности их выхода
Короткое упражнение: сигнатура
Неизменяемая модель и сигнатура
Реализация требования сортировки
Использование sortShows
Поворот
Обработка данных, поступающих из внешнего мира
Функциональный дизайн: конструирование из небольших блоков
Парсинг строк в неизменяемые объекты
Парсинг списка — это парсинг одного элемента
Парсинг списка путем парсинга каждого элемента отдельно
Парсинг String в TvShow
А как насчет возможных ошибок?
Чистые функции не должны генерировать исключения
Является ли возврат null хорошей идеей?
Option во спасение!
Как наиболее изящно обрабатывать потенциальные ошибки
Реализация функции, возвращающей Option
Option вынуждает обрабатывать возможные ошибки
Конструирование из небольших блоков
Функциональный дизайн составляется из маленьких блоков
Написание небольшой безопасной функции, возвращающей Option
Функции, значения и выражения
Практика безопасных функций, возвращающих Option
Как распространяются ошибки
Значения представляют ошибки
Option, for-выражения и контролируемые исключения...
Не лучше ли использовать контролируемые исключения?
Условное восстановление
Условное восстановление в императивном стиле
Условное восстановление в функциональном стиле
Контролируемые исключения не комбинируются друг с другом, в отличие от значений Option!
Как работает orElse
Практика функциональной обработки ошибок
Функции комбинируются даже при наличии ошибок
Компилятор напоминает, что ошибки должны быть обработаны
Ошибки компиляции нам на пользу!
Преобразование списка значений Option в простой список
Пусть компилятор будет нашим проводником...
... но не будем слишком доверять компилятору!
Перерыв на кофе: стратегии обработки ошибок
Объяснение для перерыва на кофе: стратегии обработки ошибок
Две разные стратегии обработки ошибок
Максимально эффективная стратегия обработки ошибок
Стратегия обработки ошибок «все или ничего»
Стратегия обработки ошибок «все или ничего»
Реализация стратегии «все или ничего» в parseShows
Свертка списка значений Option в значение Option со списком
Теперь мы знаем, как обработать множество ошибок одновременно!
Как узнать, в чем причина неудачи
Мы должны передать информацию об ошибке в возвращаемом значении
Он называется Either
Передача сведений об ошибке с использованием Either
Переход на использование Either
Возврат Either вместо Option
Практика безопасных функций, возвращающих Either
Навыки работы с Option пригодились и для работы с Either
Перерыв на кофе: обработка ошибок с использованием Either
Объяснение для перерыва на кофе: обработка ошибок с использованием Either
Работа с Option/Either
Резюме
Обрабатывайте ошибки без использования null и исключений
Убедитесь, что обрабатываете все пограничные случаи
Сообщите о возможности ошибки в сигнатуре функции
Конструируйте большие функции из маленьких при наличии возможных ошибок
Возвращайте описательные ошибки
7. Требования как типы
Моделирование данных для минимизации ошибок программистов
Каталог музыкантов
Хорошо смоделированные данные не лгут
Проектирование с использованием уже известного нам (простых типов)
Реализация поведения, использующего данные
Использование данных, смоделированных как простые типы
Перерыв на кофе: недостатки простых типов
Объяснение для перерыва на кофе: недостатки простых типов
Проблемы использования простых типов в моделях
Использование простых типов усложняет нашу работу!
Новые типы защищают от передачи параметров не на своих местах
Добавляем новые типы
Использование новых типов в моделях данных
Практика использования новых типов
Гарантии возможности только допустимых комбинаций данных
Моделирование сложных объектов
Использование Option для описания данных
Моделирование возможности отсутствия данных
Изменения в модели вызывают изменения в логике
Использование данных, смоделированных как значения Option
Функции высшего порядка решают!
Вероятно, для решения этой проблемы существует функция высшего порядка!
Перерыв на кофе: forall/exists/contains
Логика поиска пользователей
Объяснение для перерыва на кофе: forall/exists/contains
Объединение понятий внутри одного типа-произведения
Моделирование конечных диапазонов значений
Использование типа-суммы
Улучшение модели с помощью типов-сумм
Использование комбинации «тип-сумма + тип-произведение»
Типы-произведения + типы-суммы = алгебраические типы данных (ADT)
Использование моделей на основе ADT в реализациях поведения (функциях)
Деструктуризация ADT с помощью сопоставления с образцом
Дублирование кода и правило DRY
Практика сопоставления с образцом
Новые типы, ADT и сопоставление с образцом в дикой природе
Что можно сказать о наследовании
Перерыв на кофе: проектирование функциональных данных
Объяснение для перерыва на кофе: дизайн функциональных данных
Моделирование поведения
Моделирование поведения как данных
Реализация функций с параметрами на основе ADT
Перерыв на кофе: проектирование и удобство сопровождения
Объяснение для перерыва на кофе: проектирование и удобство сопровождения
Резюме
Моделируйте неизменяемые данные, чтобы минимизировать риск ошибки
Моделируйте требования как неизменяемые данные
Ищите проблемы в требованиях с помощью компилятора
Убедитесь, что наша логика всегда выполняется на действительных данных
8. Ввод-вывод как значения
Общение с внешним миром
Интеграция с внешним API
Вызовы API календаря
Свойства операции ввода-вывода с побочным эффектом
Как операции ввода-вывода могут вести себя неправильно
Императивное решение для кода ввода-вывода с побочными эффектами
Проблемы императивного подхода к вводу-выводу
Позволит ли ФП добиться большего успеха
Ввод-вывод и использование его результата
Императивный ввод-вывод
Переплетающиеся задачи
Вычисления как значения IO
Значения IO
Значения IO в реальной жизни
Удаляем загрязнения
Запуск значений IO
Использование значений, полученных из двух операций ввода-вывода
Объединение двух значений IO в одно
Практика создания и объединения значений IO
Разделение задач при работе только со значениями
Тип IO — вирусный
Используйте IO в как можно меньшем количестве мест
IO действует как признак вероятности неудачных случаев
Перерыв на кофе: работа со значениями
Объяснение для перерыва на кофе: работа со значениями
На пути к функциональному вводу-выводу
Как быть со сбоями ввода-вывода
Программа, описываемая значением IO, может завершиться неудачей!
Помните orElse?
Отложенные и немедленные вычисления
Реализация стратегий восстановления с использованием IO.orElse
Реализация запасных вариантов с использованием orElse и pure
Практика восстановления после сбоев в значениях IO
Где должны обрабатываться потенциальные сбои
На пути к функциональному вводу-выводу с обработкой сбоев
Чистые функции не лгут даже в небезопасном мире!
Функциональная архитектура
Использование IO для сохранения данных
Перерыв на кофе: использование IO для сохранения данных
Объяснение для перерыва на кофе: использование IO для сохранения данных
Интерпретация всего как значений
Кеширование и использование кешированных значений в случае сбоя
Интерпретация повторных попыток как значений
Интерпретация неизвестного количества вызовов API как значения
sequence, traverse, flatTraverse и другие функции
Практика восприятия функциональных сигнатур
Резюме
Используйте значения для представления программ с побочными эффектами
Используйте данные из небезопасных источников
Сохраняйте данные вне программы безопасно
Покажите, что ваш код имеет побочные эффекты
Разделяйте чистый и нечистый код
9. Потоки данных как значения
Бесконечность не предел
Работа с неизвестным количеством значений
Работа с внешними нечистыми вызовами API (снова)
Функциональный подход к проектированию
Неизменяемые ассоциативные массивы
Практика неизменяемых ассоциативных массивов
Сколько вызовов IO следует сделать
Проектирование сверху вниз и снизу вверх
Проектирование снизу вверх
Проверка тенденции к увеличению
Извлечение одной валюты из таблицы
Расширенные операции со списком
Знакомство с кортежами
Упаковка и отбрасывание
Сопоставление с образцом для кортежей
Перерыв на кофе: ассоциативные массивы и кортежи
Объяснение к перерыву на кофе: ассоциативные массивы и кортежи
Функциональные пазлы
Следование за типами в восходящем проектировании
Прототипирование и тупики
Рекурсивные функции
Бесконечность и ленивые вычисления
Структура рекурсивной функции
Обработка отсутствия значения в будущем (с использованием рекурсии)
Полезность бесконечных рекурсивных вызовов
Перерыв на кофе: рекурсия и бесконечность
Функции в вашем распоряжении
Объяснение для перерыва на кофе: рекурсия и бесконечность
Создание различных программ IO с использованием рекурсии
Использование рекурсии для выполнения произвольного количества вызовов
Проблемы рекурсивной версии
Потоки данных
Потоки данных в императивных языках
Сравнение Stream в Java и IO
Вычисление значений по требованию
Потоковая обработка, производители и потребители
Типы Stream и IO
Функциональный тип Stream
Потоки в ФП — это значения
Потоки — это рекурсивные значения
Примитивные операции и комбинаторы
Потоки значений IO
Бесконечные потоки значений IO
Запуск программы ради побочных эффектов
Практика работы с потоками
Использование преимуществ потоков
Бесконечный поток вызовов API
Обработка ошибок ввода-вывода в потоках
Разделение ответственности
Скользящие окна
Ожидание между вызовами ввода-вывода
Упаковка потоков
Преимущества потоковой обработки
Резюме
Декларативное проектирование сложных потоков управления
Использование рекурсии и отложенных («ленивых») вычислений, чтобы отложить некоторые решения
Обработка потоков IO
Создание и обработка бесконечного потока значений
Изолирование функций, зависящих от времени
10. Параллельное программирование
Потоки выполнения повсюду
Декларативный параллелизм
Последовательные и параллельные вычисления
Кофе-брейк: последовательное мышление
Объяснение для кофе-брейка: последовательное мышление
Необходимость пакетной обработки
Пакетная реализация
Компромиссы пакетной обработки
Параллельный мир
Параллельное состояние
Императивный параллелизм
Мониторы и блокировки
Модель акторов
Потокобезопасные структуры данных
Атомарные ссылки
Знакомство с Ref
Обновление значений Ref
Использование значений Ref
Делаем все параллельно
parSequence в действии
Практика одновременно выполняющихся значений IO
Моделирование параллелизма
Моделирование ссылок с параллельным доступом
Моделирование последовательных и параллельных программ
Программирование с использованием ссылок Ref и волокон
Значения IO, работающие бесконечно
Кофе-брейк: параллельное мышление
Объяснение для кофе-брейка: параллельное мышление
Необходимость асинхронности
Подготовка к асинхронному доступу
Проектирование функциональных асинхронных программ
Управление виртуальными потоками вручную
Программирование функциональных асинхронных программ
Резюме
Декларативное проектирование параллельных программных потоков
Использование легковесных виртуальных потоков (fibers)
Безопасное хранение и доступ к данным из разных потоков
Асинхронная обработка потока событий
Часть III. Прикладное функциональное программирование
11. Разработка функциональных программ
Заставьте это работать, заставьте работать правильно, заставьте работать быстро
Моделирование с использованием неизменяемых значений
Моделирование предметной области и ФП
Моделирование доступа к данным
Разделение задач
Программирование с использованием интерфейсов
Мешок функций
Бизнес-логика как чистая функция
Отделение задачи доступа к данным
Язык запросов SPARQL
Интеграция с API с применением императивных библиотек и IO
1. Создание запроса SPARQL
2. Подключение к Wikidata и отправка запросов
3. Извлечение и анализ результатов запроса
Следуя проекту
Реализация действий ввода в виде значений IO
Соединение с сервером
Создание запроса и его выполнение
Анализ результатов
Отделение библиотеки ввода-вывода от других задач
Каррирование и инверсия управления
Передача соединения
Функции как значения
Передача «способа выполнения запросов»
Настройка мешка функций
Связываем все вместе
Мы заставили решение работать
Заставляем работать правильно
Утечки ресурсов
Управление ресурсами
Использование значения Resource
Мы заставили работать правильно
Перерыв на кофе: заставьте работать быстро
Объяснение для перерыва на кофе: заставьте работать быстро
Резюме
Создавайте по-настоящему функциональные приложения
Моделируйте сложные требования как типы
Интегрируйте приложения с API внешних источников данных, используя IO
Избегайте утечек ресурсов
Кешируйте результаты запроса для ускорения выполнения
12. Тестирование функциональных программ
У вас есть тесты?
Тесты — это просто функции
Выбор функций для тестирования
Тестирование на примерах
Практика тестирования на примерах
Создание хороших примеров
Генерирование свойств
Тестирование на основе свойств
Тестирование путем предоставления свойств
Делегирование работы путем передачи функций
Интерпретация сбоев тестов на основе свойств
Что такое упрощения
Ошибка в тесте или в программе?
Нестандартные генераторы
Использование нестандартных генераторов
Тестирование более сложных случаев в удобочитаемой форме
Поиск и исправление ошибок в реализации
Перерыв на кофе: тесты на основе свойств
Объяснение для перерыва на кофе: тесты на основе свойств
Свойства и примеры
Охват требований
Тестирование требований с побочными эффектами
Определение правильного теста для работы
Тесты для проверки использования данных
Практика имитации внешних сервисов с использованием IO
Тестирование и дизайн
Тесты для проверки интеграции с сервисами
Тестирование низкоуровневой интеграции с внешними API
Локальные серверы как значения Resource в интеграционных тестах
Написание изолированных интеграционных тестов
Интеграция с сервисом — единая ответственность
Перерыв на кофе: написание интеграционных тестов
Объяснение для перерыва на кофе: написание интеграционных тестов
Интеграционные тесты выполняются дольше
Интеграционные тесты на основе свойств
Выбор правильного подхода к тестированию
Разработка через тестирование
Написание теста для несуществующей функции
Красный, зеленый, рефакторинг
Делаем тесты зелеными
Добавление красных тестов
Последняя итерация TDD
Резюме
Тестируйте чистые функции, определяя примеры
Тестируйте чистые функции, определяя свойства
Тестируйте побочные эффекты, не используя библиотеки имитаций
Разрабатывайте новые функции через TDD
Последний танец
Приложение. Памятка по Scala
Определение значения
Определение функции
Вызов функции
Создание неизменяемых коллекций
Передача функции по имени
Передача анонимной функции
Передача анонимной функции с двумя параметрами
Определение функций с несколькими списками параметров (каррирование)
Объект Math
Определение case-класса (типа-произведения) и создание его значения
Точечный синтаксис для доступа к значениям в case-классе
Синтаксис определения анонимных функций с символом подчеркивания
Отсутствующая реализация: ???
Интерполяция строк
Передача многострочной функции
Автоматическое определение типов и пустые списки
Автоматическое определение типа и форсирование типа
Определение for-выражения
Объекты как модули и объект как «мешки» типов и функций
Определение непрозрачного типа (newtype)
Импорт всего из объекта с использованием синтаксиса подчеркивания
Создание и использование значения непрозрачного типа
Определение перечислений (типов-сумм)
Сопоставление с образцом
Именование параметров в конструкторах и функциях классов
Использование интерфейсов trait для определения пакетов функций
Создание экземпляров интерфейсов trait (пакетов функций)
Значение Unit в Scala
Создание неизменяемого типа Map
Передача функций, соответствующих образцу
Игнорирование значения с помощью символа подчеркивания
Протяженность интервалов времени и большие числа
Приложение. Жемчужины функционального программирования