- Введение в функциональное программирование
- Функции первого класса
- Они могут быть назначены переменным
- Их можно использовать в качестве аргумента для других функций
- Они могут быть возвращены функциями
- Функции Более Высокого Порядка
- Декларативное программирование
- Декларативный против Императивного
- Неизменность
- константа
- Объект.назначить()
- сцепление()
- фильтр()
- Чистота
- Преобразования данных
- Массив.карта()
- Массив.уменьшить()
- Рекурсия
- Композиция
- Составление в простом JS
- Сочинение с помощью lodash
Введение в функциональное программирование
Функциональное программирование (FP) – это парадигма программирования с некоторыми особыми техниками.
В языках программирования вы найдете чисто функциональные языки программирования, а также языки программирования, которые поддерживают методы функционального программирования.
Haskell, Clojure и Scala являются одними из самых популярных чисто функциональных языков программирования.
Популярными языками программирования, поддерживающими методы функционального программирования, являются JavaScript, Python, Ruby и многие другие.
Функциональное программирование не является новой концепцией, на самом деле его корни уходят в 1930-е годы, когда родилось лямбда-исчисление, и повлияло на многие языки программирования.
В последнее время FP набирает обороты, так что сейчас самое подходящее время узнать об этом.
В этом курсе я познакомлю вас с основными концепциями функционального программирования, используя в примерах кода JavaScript.
Функции первого класса
В функциональном языке программирования функции являются гражданами первого класса.
Они могут быть назначены переменным
const f = (m) => console.log(m) f('Test')
Поскольку функция может быть назначена переменной, они могут быть добавлены к объектам:
const obj = { f(m) { console.log(m) } } obj.f('Test')
а также к массивам:
const a = [ m => console.log(m) ] a[0]('Test')
Их можно использовать в качестве аргумента для других функций
const f = (m) => () => console.log(m) const f2 = (f3) => f3() f2(f('Test'))
Они могут быть возвращены функциями
const createF = () => { return (m) => console.log(m) } const f = createF() f('Test')
Функции Более Высокого Порядка
Функции, которые принимают функции в качестве аргументов или возвращают функции, называются Функциями более высокого порядка .
Примеры в стандартной библиотеке JavaScript включают Массив.карта()
, Массив.фильтр()
и Array.reduce()
, который мы увидим чуть позже.
Декларативное программирование
Возможно, вы слышали термин “декларативное программирование”.
Давайте рассмотрим этот термин в контексте.
Противоположностью декларативного является императивный .
Декларативный против Императивного
Императивный подход – это когда вы сообщаете машине (в общих чертах), какие шаги ей необходимо предпринять, чтобы выполнить работу.
Декларативный подход – это когда вы сообщаете машине, что вам нужно сделать, и позволяете ей разобраться в деталях.
Вы начинаете мыслить декларативно, когда у вас достаточно уровня абстракции, чтобы перестать рассуждать о низкоуровневых конструкциях и больше думать на более высоком уровне пользовательского интерфейса.
Кто-то может возразить, что программирование на языке Си более декларативно, чем программирование на ассемблере, и это правда.
HTML является декларативным, поэтому, если вы используете HTML с 1995 года, вы фактически создаете декларативные пользовательские интерфейсы более 20 лет.
JavaScript может использовать как императивный, так и декларативный подход к программированию.
Например, декларативный подход к программированию заключается в том, чтобы избегать использования циклов и вместо этого используйте конструкции функционального программирования, такие как map
, уменьшать
и фильтровать
, потому что ваши программы более абстрактны и менее сосредоточены на том, чтобы сообщать машине о каждом шаге обработки.
Неизменность
В функциональном программировании данные никогда не меняются. Данные являются неизменяемыми .
Переменная никогда не может быть изменена. Чтобы обновить ее значение, вы создаете новую переменную.
Вместо изменения массива, чтобы добавить новый элемент, вы создаете новый массив путем объединения старого массива и нового элемента.
Объект никогда не обновляется, но копируется перед его изменением.
константа
Вот почему ES2015 const
так широко используется в современном JavaScript, который охватывает концепции функционального программирования: для обеспечения неизменности переменных.
Объект.назначить()
ES2015 также предоставил нам Object.assign(), который является ключом к созданию объектов:
const redObj = { color: 'red' } const yellowObj = Object.assign({}, redObj, {color: 'yellow'})
сцепление()
Для добавления элемента в массив в JavaScript мы обычно используем метод push()
для массива, но этот метод изменяет исходный массив, поэтому он не готов к FP.
Вместо этого мы используем метод concat()
:
const a = [1, 2] const b = [1, 2].concat(3) // b = [1, 2, 3]
или мы используем оператор распространения:
const c = [...a, 3] // c = [1, 2, 3]
фильтр()
То же самое относится и к удалению элемента из массива: вместо использования pop()
и splice()
, которые изменяют исходный массив, используют array.filter()
:
const d = a.filter((v, k) => k < 1) // d = [1]
Чистота
A чистая функция :
- никогда не изменяйте ни один из параметров, которые передаются ему по ссылке (в JS, объектах и массивах): их следует считать неизменяемыми. Конечно, он может изменить любой параметр, скопированный по значению
- на возвращаемое значение чистой функции не влияет ничего, кроме ее входных параметров: передача одних и тех же параметров всегда приводит к одному и тому же результату
- во время своего выполнения чистая функция ничего не меняет за ее пределами
Преобразования данных
Поскольку неизменяемость является такой важной концепцией и основой функционального программирования, вы можете спросить, как могут изменяться данные.
Просто: данные изменяются путем создания копий .
Функции, в частности, изменяют данные, возвращая новые копии данных.
Основными функциями, которые делают это, являются map и уменьшить .
Массив.карта()
Вызов Array.map()
для массива создаст новый массив с результатом функции, выполняемой для каждого элемента исходного массива:
const a = [1, 2, 3] const b = a.map((v, k) => v * k) // b = [0, 2, 6]
Массив.уменьшить()
Вызов Array.reduce()
для массива позволяет нам преобразовать этот массив во что угодно другое, включая скаляр, функцию, логическое значение, объект.
Вы передаете функцию, которая обрабатывает результат, и отправную точку:
const a = [1, 2, 3] const sum = a.reduce((partial, v) => partial + v, 0) // sum = 6
const o = a.reduce((obj, k) => { obj[k] = k; return obj }, {}) // o = {1: 1, 2: 2, 3: 3}
Рекурсия
Рекурсия – ключевая тема в функциональном программировании. когда функция вызывает саму себя , она называется рекурсивной функцией .
Классическим примером рекурсии является вычисление последовательности Фибоначчи (N = (N-1 + N-2)), здесь в ее 2 ^N совершенно неэффективном (но приятном для чтения) решении:
var f = (n) => n <= 1 ? 1 : f(n-1) + f(n-2)
Композиция
Композиция – еще одна ключевая тема функционального программирования, веская причина включить ее в список “ключевые темы”.
Композиция – это то, как мы генерируем функцию более высокого порядка, комбинируя более простые функции .
Составление в простом JS
Очень распространенный способ создания функций в обычном JavaScript – это их объединение в цепочку:
obj.doSomething() .doSomethingElse()
или, также очень широко используемый, путем передачи выполнения функции в функцию:
obj.doSomething(doThis())
Сочинение с помощью lodash
В более общем плане составление – это процесс составления списка из множества функций для выполнения более сложной операции.
lodash/fp
поставляется с реализацией compose
: мы выполняем список функций, начиная с аргумента, каждая функция наследует аргумент от возвращаемого значения предыдущей функции . Обратите внимание, что нам нигде не нужно хранить промежуточные значения.
import { compose } from 'lodash/fp' const slugify = compose( encodeURIComponent, join('-'), map(toLowerCase), split(' ') ) slufigy('Hello World') // hello-world
Оригинал: “https://flaviocopes.com/javascript-functional-programming/”