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

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

А затем наша база кода становится все больше и больше, и после определенного момента нам приходится разбираться с ошибками. А-а-а!

Исправление ошибок в большинстве случаев - утомительный процесс, потому что вам приходится сталкиваться с потенциальными виновниками, а иногда их бывает много! Мы их исправляем, потом у нас появляется больше ошибок, и порочный круг продолжается! В какой-то момент мы можем просто взглянуть на нашу базу кода и в конечном итоге сказать, что это работает, хотя я действительно не знаю, как это сделать! Это магия! : D

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

Состояние приложения

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

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

Как насчет разделения выполнения логики и обновлений состояния? Другими словами, что, если мы разделим нашу кодовую базу на чистые функции и изменения состояния (также известные как побочные эффекты)?

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

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

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

Побочные эффекты

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

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

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

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

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

Функции являются гражданами первого класса в JavaScript, что означает, что:

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

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

Чистые функции

Вся идея Pure Functions состоит в том, чтобы упростить понимание вашего кода. Вы знаете входные данные и можете легко предсказать результат.

Чистые функции вдохновлены математическим определением функции. В математике функция представлена ​​уравнением:

f(x)=y 

Здесь x - это вход, а y - выход, а функция представляет только взаимосвязь между входом и выходом.

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

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

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

Давайте посмотрим на функцию входа в систему и различные способы ее реализации:

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

Другое изменение - использование «userinput» в качестве параметра, поскольку вывод нашей функции зависит от этой переменной. Это делает вывод функции более предсказуемым и надежным.

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

Декларативный стиль и возможность повторного использования кода

Еще одна вещь, в которой действительно помогает функциональное программирование, - это декларативный способ кодирования.

Декларативный и Императивный способ - это два стиля кодирования. Идея декларативного стиля кодирования состоит в том, чтобы обобщить повторяющиеся части вашего кода, чтобы наш основной код выглядел меньше и аккуратнее. Возьмем, к примеру, метод «map» и «reduce» в массиве, который в основном используется для циклического перебора значений массива. Честно говоря, сейчас я редко использую циклы for и while с массивами. Меня избаловали «карта» и «уменьшить». Вздох!

Но самое интересное в том, что "map" и "reduce" циклически перебирают массив, используя цикл for / while за кулисами. А когда вы делаете что-то за кулисами, это декларативный стиль кодирования, потому что вы не вникаете в мельчайшие детали того, как что-то должно быть сделано. Скорее вы как бы заявляете, чего хотите.

Вы определяете ‘map’ и ‘reduce’ один раз, а затем продолжаете использовать их, когда вам нужно. Взглянем:

Каррирование

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

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

Простой пример использования каррирования:

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

Функциональная композиция

Функциональная композиция - это когда вы объединяете две функции, чтобы получить функцию продукта. Способ их комбинирования - подавать выходные данные одной функции в качестве входных данных для следующей. Уравнение выглядит так:

var resultant = (x)=>f(g(x)); //here the output of function 'g' is
                                provided as input to function 'f'.

Функциональная композиция может использоваться для объединения нескольких функций для создания индивидуальных результатов. Это можно сделать двумя способами:

Сочинить и передать

Представьте, что у вас есть 3 функции f (), g () и h (). Вы хотите передать ввод через f, затем через g, а затем через h. Это должно выглядеть примерно так:

var output=(input)=>h(g(f(input))); 

Это выглядит сложным, чем-то похожим на ад обратных вызовов. Чтобы избежать такой сложности, мы можем использовать Compose и Pipe.

Compose принимает функции (f, g, h) в качестве аргументов, а затем возвращает функцию, которая выполняет ввод справа налево.

Канал похож на создание, за исключением того, что ввод выполняется слева направо. Я не вижу смысла в левом и правом, но да, в этом разница: D.

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

Теперь, как мы можем использовать функциональную композицию и каррирование вместе, чтобы создать что-то крутое? Я сделал мини-пример, чтобы показать, как мы можем использовать эти концепции для извлечения параметров из URL-адреса:

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

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

Государственное управление

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

Забавно то, что мы можем использовать функции здесь также для обновления State. Функции и функции везде! : D

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

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

Развлекайтесь с функциями!