FP for Rubists

Представьте, что вы задремали в кулуарах railsclub, но вдруг мимо вас пробежал Николай Рыжиков во второй зал.

Он представился художественным руководителем команды Health-Samurai, которая уже лет 8 занимаеться Health IT. Он шептал какие-то странные слова - ФП, персистентные структуры данных. И вы не подумав про последствия побежали за ним и ... провалились в кроличью нору (хотя Ярослав вас предупреждал:).

Толи нора была слишком глубокой, толи ... Николай слишком долго говорил. Но на 40 минут вы попали в страну Функционального программирования.

Вокруг все было похожим на привычную обстановку, но все было каким-то странным.

Во прервых все было сделанно из функций и данных. Да-да все было на оборот - мы стемимся связать поведение и данные в аккуратненькие объекты, а у них проводилась четкая грань между ними. Функции чем-то напоминали наши методы, лябмды и блоки, но тоже были странными. И почему-то по близости практически не было никаких объектов и классов.

Почему-то вокруг все говорили не "передать аргументы в функцию", а применить функцию к значениям (так там называли данные).

Толи потому-что функции за собой ухаживали, но они считали себя "чистыми" и вели они себя необычно. Напимер, функция inc`` применялась к единичке и возвращала двойку, но единичка тоже никуда не исчезала. У нас тоже есть операторы над примитивными типами, они ведут себя так же. Но здесь, даже такие с виду знакомые функции как pushэлемента в массив ничего не делали с оригинальным массивом и элементом, а возвращали новый массив содержащий элемент (как будто делали копию). Также вела себя функция добавления нового ключа вhash``.

Здесь вообще нельзя было поменять что-нибудь в данных, при любой попытке мы получали каждый раз новую измененную копию, но и старые данные тоже оставались на своих местах. Возможно поэтому функции называли чистыми, а данные значениями.

Мы попробовали несколько раз применить функцию к тем же саммым значениям, но результат был всегда одним и тем же (даже не интересно). Вне зависимости от того, что происходило вокруг, эти "чистые" функции постоянно, как автоматы, возвращали тоже самое. Хоть не вызывай их второй раз с теми же аргументами, а просто замени предыдущим результатом. За такое поведение они считали себя ссылочно-прозрачными - те во всех местах и в любое время можно было заменить вызов функции с одинаковыми параметрами, тем что они возвращают - и ничего бы не поменялось.

Эти фунции подозрительно легко склеивались, достаточно было выход одной функции соединить с входом другой (если подходили разъемы) и мы получали новую функцию, которая опять оказывалась чистой.

Вообще все программы строились как дерево соединенных подобным образом функций (у нас это обычно граф объектов). Стоило передать в такое дерево входные данные, они начинали передаваться вверх достигая листиков, а потом листики начинали схлопываться в данные. И когда все листики на веточке схлопывались, веточка превращалась в листик и тоже начинала схлопываться. И в итоге от дерева оставалось только значение. Они называли это evaluation. Причем оказывалось не очень важно в каком порядке схлопываются веточки - поскольку в результате все равно получалось тоже самое значение.

У них была своя абстактократия, некоторые функции могли принимать на вход другие функции или производить новые функции - их называли функциями высших порядков.

....

Например, была функция Fold (или reduce) при помощи, которой можно было выполнить практически любые операции с коллекциями - получить сумму, произведение, смапить, отфильтровать. Похожие функции были для работы с деревьями, они уже принимали по-несколько других функций. Ну у нас есть нечто похожее, иногда называют потоками.

Были еще забавные функции, которые могли оборачивать другие функции - те они принимали функцию - возвращая новую функцию. Это чем-то напоминало наш паттерн декоратор. Из подобных функций можно было собрать новую, нанизывая их друг на друга и добавляя новую функциональность, а потом применять ее к значениям.

Например у нас на глазах, для последовательного применения различных операций к коллекциям, вместо того чтобы приминять каждую операцию оббегая коллекцию каждый раз - они вначале собрали из таких декорирующих функций новую, содержащую все нужные операции, и лишь потом применили ее к коллекции за один проход. Им даже не понадобились ленивые коллекции, чтобы сделать это. Некоторые называли эти странные декорируемые функции для работы с коллекциями - трансдюссерами.

Еще кстати там были изменяемые данные и всякие вводы-выводы, но их считали дикими и опасными и поэтому изолировали от общества чистых функций и данных-значений. Они сидели в клетках, которые называли SТМ или IO монады, трогать их можно было только в тразакции изолированной от остального мира, ну или вообще нельзя было.

Когда несколько функций начинали работать одновременно, они вообще друг другу не мешали, поскольку у каждой были свои копии игрушек. А если им нужен был доступ к зверям - то под чутким контролем STM почему-то не удавалось устроить им гонку, или не консистентное чтение или дедлок. Так что было даже не интересно, никакого риска и адреналина.

Мы как веб-программисты, конечно же отправились туда где из этих функций делают веб-приложения.

Веб сервер Роутинг Вью Генерация SQL Сервисы и контроллеры Весь стэк