Прочитав “Грокаем функциональное мышление” решил добить эту тему и прочитать следом эту книгу, при этом ни на что особо не надеясь. Оказалось, напрасно :) Книги между собой слабо пересекаются, хотя обе знакомят с функциональным программированием. Причем, эта оказалась мне и ближе, и интереснее, хотя бы из-за выбора языка, Java и дальше - Scala.
В прочем, начало было предсказуемым, объясняли чем отличаются декларативный стиль от императивного, что такое чистые функции. Так как я не очень хорошо знаю Java, то для меня было новостью то, что она поддерживает функции первого порядка. С одной стороны круто, с другой стороны - очень зубодробительный там синтаксис, все же.
В целом, в первой части снова описывались такие функции, как map(), filter() и всякими другими, вроде foldLeft. На это раз все больше и больше кода было написано на Scala, а код на Java теперь встречается только для иллюстрации императивных решений.
Начали использовать обратные вызовы и замыкания, и даже функции, которые возвращают функции, которые возвращают функции. Это сделано для того, что бы можно было преобразовать функцию с несколькими параметрами в функцию с одним параметром. Такой прием называется каррированием. Так же было введено такое понятия, как “тип-произведение, по сути - это класс. В этом смысле, книга повторяет содержание “Грокаем функциональное мышление” с той лишь разницей, что тут используется Scala вместо JavaScript… А, ну и никто не нудит по-поводу побочных эффектов :)
Целый решал задачи из первой части и что-то мне кажется, что конструкции типа вот такой я бы не хотел разбирать каждый день, хотя автор уверяет что это красиво. Может быть, конечно, со временем привыкаешь и они кажутся простыми, но пока это выглядит не очень
def highSciringWords(wordScore: String => Int)
:Int => List[String] => List[String] = {
higherThan => words => words.filter(word
=> wordScore(word) > higherThan)
}
Причем, это оказались цветочки, ягодки пошли потом, начиная со второй части книги. С другой стороны, материал этой книги действительно больше похож на программирование, в отличии от “функционального мышления”.
Во второй части книги пошли более продвинутые темы, вроде обработки ошибок и мне всё больше и больше кажется, что я в первую очередь изучаю Scala, а уже потом - функциональное программирование. Например, по тому что часть функций - это явно синтаксический сахар, который присутствует только в Scala и вряд ли где-то еще. Да, он помогает писать короткие и красивые функции, но как это мне поможет писать в функциональном стиле на каком-то другом языке - не понятно.
А сам вариант возврата ошибок внутри Either ничем не отличается от возврата списка аргументов, где первый, например, объект ошибки, а второй - это результат работы функции. Просто, завернут в определенный объект и часть функций языка его поддерживают “из коробки”. В общем, снова синтаксический сахар или чего-то не понял?
Познакомился с алгебраическим типом данных и прикольными конструкциями с ними. Причем, на этот раз для убедительности показали примеры не только на Scala, но еще и на F# и Haskell. Добрался до функций с побочными эффектами и способами их изоляции посредством построения ленивых вычислений. Так же познакомили с вариантом восстановления после сбоев ввода-вывода и выглядит это больше, как обучение Scala, чем ФП.
Наконец-то, добрались до рекурсий (куда же без них!), посредством которой реализовали зацикленные функции чтения/записи, по сути бесконечные циклы, в том числе и для работы со потоками. Оказалось, что в Scala есть такой прикольный финт ушами, как упаковка потоков, функция zip. Она “упаковывает” два потока, вычисления и контроля доступа к данным, в один и запускает их в волокнах (насколько бы глупо ни звучал этот термин). В общем-то, в Scala оказалось очень много такого вот сахара, который помогает какие-то алгоритмы/программы писать очень компактно.
Следом познакомили с пакетной обработкой, а следом перешли к параллелизму и такой конструкции, как Ref - это функциональная атомарная ссылка. После познакомили и с асинхронным кодом. И уже после знакомства с новыми концепциями, в отдельной главе реализовали полноценное приложение, которое включает http-запросы к Wikiledia посредством языка Sparkql, что для меня так же было неожиданностью. Заметил, что во-время проектирования приложения даже вспомнили о DDD, с его предметной областью и все такое.
Заключительной главе рассказывалось о методах тестирования приложений, на примерах юнит- и интеграционных тестов. Мельком вспомнили о TDD с его мантрой “красный, зеленый, рефакторинг”. Все это было с практикой написания тестов для приложения из предыдущей главы, наглядно. Хотя, конечно, мне не нравится идея использовать генерацию значений, по тому что поймав ошибку, все равно надо будет её выносить в отдельный кейс, что бы убедиться, что после исправления она больше не повторится никогда.
В целом, мне книга понравилась, но я бы не сказал что она для новичков, на которых нацелена серия “Грокаем..”. По крайней мере, мне так казалось до этого момента… Надо быть готовым к тому, что материал придется прорабатывать, иначе я где-то к середине книги поплыл. Своих денег она точно стоит! Жаль только оформление вызывает какой-то диссонанс, выглядит как для детей, при том что материал, повторюсь, нормальный.
Хотел сказать, что само издание повторяет серию “Грокаем…”, но в этот раз бумага была прозрачной и сильно просвечивала печать с другой стороны листа. Обидно…
Автор(ы):
- Michal Plachta
Год издания: 20241
Количество страниц: 512
Оценка: 5/5
Издатель: Питер
Ссылка на страницу книги на сайте издательства: https://www.piter.com/collection/all/product/grokaem-funktsionalnoe-programmirovanie
Оригинальное название: Grokking Functional Programming
Год издания оригинала: 2022
-
фактически, осень 2023, презентация на Хабре -> https://habr.com/ru/companies/piter/articles/764210/ ↩︎