Если вам интересно прочитать эту статью на испанском языке, загляните в мой блог The Developer’s Dungeon.

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

Я очень много работал над редизайном своего сайта и блога.
Эта статья была размещена там первой, как всегда, на испанском языке
Вы можете проверить ее здесь, надеюсь, она вам понравится.

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

  • что такое функция с математической точки зрения
  • что такое функциональная композиция и почему это важно
  • что такое чистые функции

Эти понятия сегодня очень пригодятся для дальнейшего изучения ФП.
Если вы не читали мою предыдущую статью, то можете сделать это здесь.

Эта новая часть очень практична, множество примеров JavaScript, так что давайте приступим к ней.

Функционирует как «граждане первого класса»

ВТФ? Давайте помедленнее, эта концепция означает, что в JavaScript и функциональных языках, таких как Haskell или Clojure, функции являются фундаментальным элементом языка, поскольку как они могут быть использованы, как любой другой тип переменной.

Мы можем передавать функции другим функциям в качестве параметров и можем возвращать функции как произведение других функций. Классический пример — обратные вызовы в JavaScript:

http.get("some/api", params, function(err, data, response) {
  if(!err) {
    // Here would be the code that
    // handle a positive API response
  } else {
    console.log(err)
  }
})

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

Еще один взгляд на композицию функций

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

function isBiggerThanThree(value) {
  return value > 3
}

function mapBoolToHumanOutput(value) {
  return value ? "yes": "no"
}

const result = mapBoolToHumanOutput(isBiggerThanThree(3))

Таким образом мы получаем сложный результат на основе 2-х небольших функций, но есть ли другой способ? ДА! Мы можем использовать функцию справки, подобную следующей:

const compose = (...fns) => x => fns.reduceRight ((v, f) => f(v), x)

Эта функция является классической из функциональных языков, большинство из них уже включают ее в основную языковую библиотеку, JavaScript к сожалению, нет, к счастью, такие библиотеки, как RamdaJs (или любая другая библиотека, реализующая « Спецификация FantasyLand") включает функцию в JavaScript.
Эта функция просто получает любое количество функций в качестве параметров, и при условии, что она соответствует математическим правилам композиции, которые мы видели в предыдущем article, он возвращает новую функцию, которая сочетает в себе поведение всех предыдущих. Давайте посмотрим на пример:

function isBiggerThanThree(value) {
  return value > 3
}

function mapBoolToHumanOutput(value) {
  return value ? "yes": "no"
}

const biggerThanThreeAndMapOutput = compose(
  mapBoolToHumanOutput,
  isBiggerThanThree
)

biggerThanThreeAndMapOutput(3)

Разве это не потрясающе? А что, если мы также хотим протоколировать результаты?

const biggerThanThreeAndMapOutputAndLogIt = compose(
  console.log,
  mapBoolToHumanOutput,
  isBiggerThanThree
)

biggerThanThreeAndMapOutputAndLogIt(3)

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

  1. Это позволяет нам создавать более читаемый код без необходимости объединять 3 функции одну за другой для получения результата.
  2. Это позволяет нам создать эту функцию без необходимости ее выполнения, мы определяем новую функцию и можем делать с ней все, что захотим.
  3. Поскольку функции являются «гражданами первого класса» в JavaScript, мы можем передавать эту функцию другим в качестве параметров, тогда мы можем создавать различные функции во время выполнения и, таким образом, изменять работу нашей программы в соответствии с нашими потребностями.
  4. Используя композицию функций, мы избавляемся от необходимости определять промежуточные переменные, не теряя при этом удобочитаемости кода. При выполнении нашей составной функции результат автоматически передается от одной функции к другой.

Продолжаем, впереди еще много интересного 😀

карри

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

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

Давайте посмотрим на пример, чтобы понять это:

// No Currying
function sumTwoValues(x, y) {
  return x + y
}

sumTwoValues(2, 2) // = 4

// With Currying
function sumTwoValues(x) {
  return y => {
    return x + y
  }
}

sumTwoValues(2)(2) // = 4

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

// No Currying
function sumTwoValues(x, y) {
  return x + y
}

sumTwoValues​​(2, 2) // = 4

// With Currying - Using R.curry from RamdaJs

const curryiedSum = R.curry(sumTwoValues)

curryiedSum(2)(2) // = 4

Какая польза от этого, спросите вы? Еще немного, мы почти у цели.

Частичное применение функции

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

// Using R.curry de RamdaJs
function sumTwoValues(x, y) {
  return x + y
}

const curryiedSum = R.curry(sumTwoValues)

// curryiedSum is a function that receives a single parameter
// and returns a function that receives the second parameter
// therefore we could do this

const addTen = curryiedSum(10)

// addTen is a new function, which when executed will add 10 to the parameter we choose
// this is known as partial application
addTen(30) // = 40

Давайте повторим, что мы узнали, эта «addTen» — новая функция, мы можем делать с ней что хотим, передавать ее другим частям кода или компоновать с другими функциями.

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

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

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

Первоначально опубликовано на https://dev.to 26 февраля 2020 г.