Функциональное программирование и его применение в JavaScript

2
6686
Добавить в избранное

В последнее время React и Redux продвинули в массы функциональное программирование, но не все освоили его. Давайте разбираться.

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

Прежде чем мы рассмотрим, что такое функциональное программирование, полезно будет узнать, когда оно чаще всего используется. Например, при преобразовании данных «один в один»:

В приведенном выше фрагменте кода представлены типы хранилища, компонента и функционального слоя между ними.

Код типа convertUserMapToArray, преобразует данные из хранилища, в формат, подходящий для пользовательского интерфейса.

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

ФП – это процесс создания ПО при помощи «чистых» функций. Чистая функция – это функция без сайд-эффектов, имеющая одно входное и одно выходное значение.

Основы функционального кодинга и его применение в JavaScript

Например, мы можем быть уверены, что 2 + 2 = 4, а 3 x 3 = 9.

Побочные эффекты (сайд-эффекты)

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

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

Рассмотрим несколько примеров побочных эффектов.

Мутация

Изменение переданного аргумента.

В приведенном выше примере изменяется значение arr по ссылке. В результате, мы не можем предугадать, что вернет эта функция.

Разделяемое состояние

Использование какой-либо формы глобального состояния функционального программирования.

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

Асинхронный код

Код, который не выполнится немедленно.

Этот пункт заслуживает особого внимания. Часто нужно сделать что-то асинхронно, каким-либо образом обратиться к API, получить данные и т. д. Это отсылка к пункту о побочных эффектах – они должны быть изолированы, чтобы сделать код более предсказуемым и понятным.

Декларативный и императивный код

Декларативный код описывает, что он делает:

Императивный код описывает, как он это делает:

Верхний блок написан на React с использованием декларативной библиотеки. Он сообщает: «Мы хотим счетчик на странице».

Нижний блок использует vanilla JS. Он явно находит ноду DOM и обновляет ее. Для маленького примера – это нормально, но в крупном проекте могут возникнуть проблемы с масштабированием. Код на React выглядит проще и компактнее, а с vanilla JS все обстоит иначе.

Примеры

Императивный код

Декларативный код

Две данные функции выполняют одно действие – берут список файлов и возвращают словарь, где ключом является file.id.

Императивный код более неряшлив (8 строк кода, вместо 3), а из-за этого больше мест для появления ошибок.

Функциональные концепции

Разделение

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

Композиция

Функциональное программирование и его применение в JavaScript

Все описанные функции выполняют преобразование аргумента. Первая – сортирует список файлов, вторая – возвращает массив файлов с расширением PDF, а последняя функция реализует преобразование списка 1:1 в его новую “версию”, просматривая список файлов и возвращая ключ каждого из них.

Неизменность

Данное понятие подразумевает под собой тот факт, что информация не может изменяться после создания.

Memoization

Memoization – это метод оптимизации, используемый в основном для ускорения работы ПО путем сохранения результатов функций и возврата кэшированного результата при повторном вводе тех же данных.

Функции высокого порядка

В математике и информатике функцией высокого порядка называется функция, выполняющая по крайней мере одно из следующих действий:

  • принимает одну или несколько функций в качестве аргументов (т. е. процедурных параметров);
  • возвращает функцию в качестве результата.

Кажется сложным, но вы, скорее всего, уже использовали такие функции в своем коде когда использовании функциональное программирование, не осознавая этого.

Функция, принимающая функцию

Это просто обратный вызов – функция высокого порядка принимает в качестве аргумента анонимную функцию.

Функция, возвращающая функцию

Еще одна штука, которую вы, вероятно, делали раньше, – это замыкания. В данном случае counterGenerator является функцией высокого порядка, поскольку возвращает функцию.

Функция, которая принимает и возвращает функцию

Последняя форма функции – симбиоз:

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

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

Это метод конвертации функции, принимающей несколько аргументов (или кортеж аргументов) в последовательность функций с одним аргументом.

Есть sum, принимающая аргументы a, b и c. Когда sum передается в lodash.curry (функция высокого порядка), она становится новой функцией и продолжает возвращать функции, пока a, b и c не будут обработаны.

Если на вход передать аргументы 1, 2, 3, то функция вернет 6. Если передать только 2, 3 – вернется новая функция, ожидающая еще одного аргумента.

Частичное применение

При частичном применении мы можем взять функцию и привязать к ней готовые аргументы оригинальной функции. Рассмотрим пример:

Функция learn Spell, принимающая в параметрах заклинание и волшебника. Если эту функцию с заклинанием передать в lodash.partial, будет создана новая функция, которая обучит мага предопределенному заклинанию (learn Expelliarmus и learn Expecto Patronum).

Подобный пример был рассмотрен в разделе о композиции:

Данные функции частично передают аргумент функции lodash. Это эквивалентно такому блоку:

Чего можно добиться оптимизацией

Это не попытка сократить строки кода – здесь все намного серьезнее:

  • сделать код более читабельным и простым;
  • упростить код для тестов;
  • сделать пользователей счастливее.

Оригинал

Другие материалы по теме:

Хотите получать больше интересных материалов с доставкой?

Подпишитесь на нашу рассылку:

И не беспокойтесь, мы тоже не любим спам. Отписаться можно в любое время.




Комментариев: 2

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

  2. Дальше этого определения не стал читать.

Добавить комментарий