InterLink Meetup. Functional Programming

Тема функціонального програмування була обрана не випадково. Чимало бібліотек та фреймворків вже досить активно використовують принципи, які під своїми математичними стовпами об’єднала ця екзотична парадигма програмування. Angular активно використовує RxJS, який в свою чергу базується на принципах ФП. Redux, нині популярна бібліотека для управління станом веб-додатку, привчає нас породжувати нові версії незмінних станів, використовуючи чисті функції. І врешті-решт, навіть вирішення повсякденних задач з обробки даних в таких імперативних мовах як Java та JavaScript стає значно легшою та наочнішою за виростанням функціонального підходу. Саме прикладне використання принципів ФП в контексті мов JavaScript та Java ми й розглянули разом з нашими гостями та менторами.

Принципи ФП у JavaScript

На мітапі ми сконцентрувались на найбільш важливих, з точки зору практичного використання принципах. Це незмінність даних, чисті функції, а також функції першого класу та вищого порядку. Ми не хотіли занадто ускладнювати й до того непросту тему, тож розглянули її на простій, вже звичним для всіх студентів темі – геометричних фігурах та операцій над ними. Через послідовність перетворення коду та заміщення емпіричного підходу на декларативний, ми прийшли до чіткого та лаконічного опису функції. Порівняйте описані нижче два варіанті розрахунку загальної площі квадратів серед набору прямокутників мовою програмування JavaScript. В другому прикладі ми використали функціональну версію бібліотеки Lodash.

Приклад №1. Імперативний розрахунок загальної площі квадратів


Приклад №2. Функціональний розрахунок загальної площі квадратів

Фільтрація: наприклад відібрати тільки квадрати або тільки червоні прямокутникиВ прикладах синім виділена частина коду, яка буде повторюватись між різними варіантами задач з обробки прямокутників. В Таблиці №1 наведено приблизний список можливих операцій. Всі операції поділені на три типи:

  1. Обробка кожного прямокутника: розрахунок площі, периметру чи діагоналі
  2. Агрегація: узагальнення отриманих даних у вигляді суми, мінімального чи максимального значення

Навіть з таким невеликим набором ми отримаємо 2 * 3 * 4 = 24 функцій, в кожній з яких буде дублюватись частина коду, виділена синім кольором у прикладі № 1. Натомість, все що відрізнятиме їх між собою – це конкретні критерії фільтрації, стратегії обчислення та агрегації.

Таблиця №1. Варіативність стадій обробки прямокутників

Filter Mapping Aggregation
form area min
color perimeter max
diagonal sum
average

Хоче дізнатись більше деталей? Запрошую вас до перелгяду відео-запису лекциї.

Інтерактив

Після порції теорії та прикладів прийшов час для інтерактиву. Він, вже традицій для наших мітапів, проходить на межі цифрових технологій та фізичного світу. Цього разу гості в прямому сенсі цього слова складали програму обробки тих самих прямокутників з вже наявних функцій у вигляді карток з їх назвами.

Для початку ми закріпили на практиці вже продемонстровані в коді приклади. Далі задача ускладнилась, і гості мали використати існуючі блоки ще в небаченому до цього поєднанні. В прикладі №3 наведено дві функції, які дозволяють поєднувати декілька критеріїв відбору елементів (предикатів) в один. Функція or поєднує два предикати в один, який буде істинним, якщо хоча б один з двох предикатів істинний. Функція any приймає список предикатів і повертає новий предикат, який буде істинним якщо хоча б один предикат з усього списку істинний. Краса цього прикладу в тому, що функцію reduce, яку ми раніше застосовували для того, що б скласти усі числа зі списку та порахувати суму, або знайти максимальне значення числа, тепер використовується для обробки списку функцій, послідовно “додаючи” їх за допомогою функції or. Ми поєднуємо усі функції в одну нову функцію, яка перевіряє, чи має якийсь елемент один з трьох кольорів: червоний, зелений чи синій.

Приклад №3 Перевірка по одному з критеріїв

let isRed = r => r.color == 'red';
let isGreen = r => r.color == 'green';
let isBlue = r => r.color == 'blue';

let or = curry((l, r, a) => l(a) || r(a));
let any = reduce(or, _ => false);
let isRGB = any([isRed, isGreen, isBlue]);

isRGB({ color: 'red' }); // true
isRGB({ color: 'green' }); // true
isRGB({ color: 'yellow' }); // false

ФП та Java 8

Закріпивши основи інтерактивом, ми перейшли до використання функціонального підходу на Java 8. Розглянули набір можливостей Java 8, які в поєднанні дозволяють імітувати використання функцій першого класу: функціональні інтерфейси, посилання на методи та лямбда вирази. А наостанок виявили принципову різницю між розглянутими підходами в JavaScript та Java. Полягає вона в тому, що в JavaScript набір даних повністю має пройти через одну стідію обробки, щоб перейти до іншої. В Java Stream API, натомість, кожен елемент з потоку проходить всі проміжні стадії обробки.

Ділитися знаннями – це класно, тому під час кава-брейку наші гості мали змогу поспілкуватися  з досвідченими тімлідами та менторами InterLink, отримати відповіді на хвилюючі запитання та дозу мотивації :).

Як би не було нам класно в колі наших гостей, але InterLink Meetup добіг кінця. А ми чекаємо на вас на новій зустрічі, яка відбудеться незабаром ;).

Post A Reply