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

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

Поскольку это курс на целый день, и будет рассмотрено множество тем, мы разделим его содержание на две публикации:

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

Удачи и не забудьте оставить свои вопросы в комментариях ниже!

Прежде чем ты начнешь…

  • Убедитесь, что у вас установлена ​​NodeJS версии 8.
  • Вы можете запускать примеры в интерфейсе командной строки, если запускаете node -i, но при работе над упражнениями лучше создать файл с вашим JavaScript.
  • Чтобы добавить немного остроты к упражнениям, используйте TypeScript, а не JavaScript!

Карта и фильтр

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

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

Пример:

var array = [1, 2, 3];
var double = array.map(n => n * 2);
console.log(double);

Это вызовет функцию n => n * 2 сначала с аргументом n = 1, получив 2 в качестве промежуточного результата, затем с n = 2 получением 4 и, наконец, с n = 3 получением 6. Окончательный результат будет [2, 4, 6].

Учитывая некоторый массив чисел:

var input = [1, 2, 3, 4, 5]

🎓 Используйте старомодный цикл (например, for) для создания и заполнения нового массива, который содержит степень двух из этих чисел.

🎓 Выполните то же преобразование, используя функцию карты.

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

var array = ["alice", "bob", "charles"];
var keep = [];
for (var i = 0; i < array.length; i++) {
  var current = array[i];
  if (current[0] === "b") {
    keep.push(current); 
  }
}

Вместо этого сегодня вы научитесь делать следующее:

var array = ["alice", "bob", "victor"];
var keep = array.filter(name => name[0] === "b");

Это 2 строки вместо 8!

Учитывая список покупок:

var items = ["banana", "apple", "spaghetti", "football", "eggplant", "bread"];

🎓 Выбирайте только те, которые содержат букву «р»

🎓 Преобразуйте каждый выбранный элемент (строку) в объект, который выглядит следующим образом:

{ name: "e.g. football", amount: 1 }

У вас должен получиться массив из 3 объектов, каждый из которых имеет имя и свойство amount. Очевидно, вы должны делать это без использования каких-либо циклов!

Уменьшать

Допустим, вы создали массив чисел:

var numbers = [1, 3, 5, 6, 7, 10, 15, 16, 19, 22, 26, 29, 32, 35, 39];

И вы выбрали четные числа:

var even = numbers.filter(n => n % 2 === 0);

Что, если вы хотите просуммировать эти числа? Карта не уведет вас далеко, потому что она будет работать только с отдельными числами в коллекции. Вы не хотите использовать цикл для простого добавления одного числа к другому, потому что циклы устарели и нечитаемы! Уменьшить - это решение.

var sum = even.reduce((a, b) => a + b);

Reduce принимает коллекцию (в данном случае массив) и функцию для объединения двух значений. Он вставит первые два значения массива, чтобы начать, и, используя результат, будет продолжать «уменьшать» до тех пор, пока не останется только одно значение.

Когда дело доходит до чисел, особенно с плавающей запятой, у Javascript есть несколько очень интересных характеристик. Короче говоря, Javascript может давать неожиданные результаты при сложении или умножении десятичных чисел и при работе, например. с деньгами это очень нежелательно. Вы можете много прочитать о числах с плавающей запятой в Javascript в Интернете, например Здесь или здесь. Прежде чем продолжить, убедитесь, что вы понимаете основную проблему.

🎓 Используйте Yarn (или NPM) для установки Big.js

Добавление 0.2 и 0.1 в Javascript не равно 0.3. Если вы хотите попробовать это, введите node -i в свой терминал, а после этого введите .1 + .2 и закончите вводом.

Допустим, мы создаем сайт электронной коммерции и хотим иметь дело с деньгами, поэтому нам нужны точные расчеты. Мы получим этот список товаров в корзине:

var cart = [
	{
	  name: "eggplant",
	  price: 0.1,
	  onlineCheckout: true
	},
	{
	  name: "footbal",
	  price: 10.5,
	  onlineCheckout: false
	},
	{
	  name: "banana",
	  price: 0.2,
	  onlineCheckout: true
	}
];

🎓 Выбирать в корзине только те товары, для которых верно onlineCheckout.

🎓 Преобразуйте цены в объекты Big.js с помощью конструктора Big (например, Big(1))

🎓 Суммируйте полученные цены. Используйте сокращение и используйте метод Big (). Plus для сложения чисел (НЕ встроенный оператор +)

Рекурсия

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

Их вдохновила первая неделя «Функционального программирования на Scala», одного из лучших курсов по функциональному программированию, который можно найти на Coursera (вы можете просмотреть материалы бесплатно).

Треугольник Паскаля

Следующий набор чисел называется треугольником Паскаля:

    1
   1 1
  1 2 1
 1 3 3 1
1 4 6 4 1

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

🎓 Выполните это упражнение, реализовав функцию паскаль, которая принимает столбец и строку в качестве аргументов, считает от 0 и возвращает число в этом месте треугольника. Например, паскаль (0,2) = 1, паскаль (1,2) = 2 и паскаль (1,3) = 3.

const pascal = (column, row) => ??? (returns an int)

Круглые скобки Балансировка

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

  • (if (zero? x) max (/ 1 x))
  • I told him (that it’s not (yet) done). (But he wasn’t listening)

🎓 Функция должна возвращать false для следующих строк:

  • :-)
  • ())(

Последний пример показывает, что недостаточно проверить, что строка содержит одинаковое количество открывающих и закрывающих скобок.

const balance = (letters) => ??? (returns true or false)

Подсказка: вы можете определить внутреннюю функцию, если вам нужно передать вашей функции дополнительные параметры.

Тестирование: вы можете использовать .split("") для преобразования строки в массив символов.

Подсчет изменений

Напишите рекурсивную функцию, которая подсчитывает, сколько разных способов вы можете внести изменения на определенную сумму, учитывая список номиналов монет. Например, есть 3 способа отдать сдачу на 4, если у вас есть монеты достоинством 1 и 2: 1 + 1 + 1 + 1, 1 + 1 + 2, 2 + 2.

🎓 Выполните это упражнение, реализовав функцию countChange. Эта функция требует изменения суммы и массива уникальных номиналов монет (например, монета 1, монета 2 и монета 5).

const countChange = (money, coins) => ??? (returns an int)

Подсказка: подумайте о вырожденных случаях. Сколькими способами вы можете отдать сдачу за 0 евро? Сколько способов вы можете отдать сдачу на ›0 евро, если у вас нет монет?

Заключение

Поздравляем, вы дошли до конца! Молодец 👍. Как тебе этот урок? Все было ясно? Остались вопросы? Дайте нам знать в комментариях ниже!

Следующий раздел можно найти здесь!