Don’ т бояться функционального программирования

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

Первоначально отнесены к летописи информатики академии, функциональное программирование была недавно возрождения, которое в значительной степени благодаря его полезности в распределенных системах (и, вероятно, также потому, что “чистые” функциональные языки, такие как Haskell трудно понять, что дает им определенное облатки) .

Жесткие функциональные языки программирования, как правило, используется, когда производительность и целостность системы являются критически — т.е. ваша программа должна делать то, что вы ожидаете в любое время и должен работать в среде, где его задачи могут быть совместно через сотни или тысячи сетевыхкомпьютеры. Clojure 1 , например, полномочия Akamai 2 , массовые содержание сеть доставки используется такими компаниями, как Facebook, в то время как Twitter лихо adopted 3 Scala 4 за большинство компонентов эффективности интенсивной и Haskell __29 | 5 используется AT& T для его сетевой безопасностиСистемы .

Эти языки имеют крутой кривой обучения для большинства интерфейсных веб-разработчиков;Однако, многие более доступным языки включают особенности функционального программирования, особенно на Python, как в своей основной библиотеки, с функциями, как map 41 ~ и | (который мы будем говорить о в немного), и с библиотеками, такими как Fn.py 6 вместе с JavaScript, еще раз, используя методы сбора, но и с библиотеками, такими как Underscore.js __43 | 7 | __8 и Bacon.js 8 .

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

Поиск согласованного определения функционального программирования является жестким, и большая часть литературы опирается на несколько предчувствие заявления, как “функции как объекты первого класса» и «устранения побочных эффектов.” Только в случае, не согните мозгузлы, на более теоретическом уровне, функциональное программирование часто объясняется в терминах лямбда calculus 9 (некоторые фактически argue 10 , что функциональное программирование в основном математика), — но вы можете расслабиться.С прагматической точки зрения, начинающий должен понимать только два понятия для того, чтобы использовать его для ежедневного применения (не требуется исчисление!) .

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

Во-вторых, функциональные программы должны быть stateless, которые в основном означает, что они должны выполнять все задачи, как будто в первый раз, не зная о том, что может или не может произойти раньше в исполнении программы (можно сказать, чтолицами без гражданства программа неведении о past __24 | | 11__3 ).В сочетании с неизменностью, это помогает нам думать о каждой функции, как если бы это были работать в вакууме, в блаженном неведении о чем-либо в приложении, помимо других функций.В более конкретном плане это означает, что ваши функции будут работать только на данных, передаваемых в качестве аргументов и никогда не будет полагаться на внешних ценностей выполнять свои расчеты .

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

Например,давайте говорить, что мы имеем ответ API:

var data = [
  { 
    name: "Jamestown",
    population: 2047,
    temperatures: [-34, 67, 101, 87]
  },
  {
    name: "Awesome Town",
    population: 3568,
    temperatures: [-3, 4, 9, 12]
  }
  {
    name: "Funky Town",
    population: 1000000,
    temperatures: [75, 75, 75, 75, 75]
  }
];

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

[
  [x, y],
  [x, y]
  …etc
]

Здесь x средняя температура, а y это размер популяции .

Без функционального программирования (или без использования, что называется “императив” стиль), наша программа может выглядеть следующим образом:

var coords = [],
    totalTemperature = 0,
    averageTemperature = 0;

for (var i=0; i < data.length; i++) {
  totalTemperature = 0;
  
  for (var j=0; j < data[i].temperatures.length; j++) {
    totalTemperature += data[i].temperatures[j];
  }

  averageTemperature = totalTemperature / data[i].temperatures.length;

  coords.push([averageTemperature, data[i].population]);
}

Даже в надуманный пример, это уже становится трудно следовать.Давайте посмотрим, если мы можем сделать лучше .

При программировании в функциональном стиле, вы всегда ищете простых повторяемых действий, которые могут быть абстрагированы в функции.Мы можем построить более сложные функции, вызывая эти функции в последовательности (также известные как “составляющих” функций) — подробнее об этом в секунду.В то же время, давайте смотреть на шаги мы берем в процессе трансформации первоначальный ответ API для структуры, необходимой нашей библиотеке визуализации.На базовом уровне, мы выполним следующие действия на нашем данных:

  • Добавить каждый номер в списке,
  • Расчета в среднем,
  • Получить одно свойство из списка объектов .

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

  1. Все ваши функции должны принять по крайней мере один аргумент .
  2. Все ваши функции должны возвращать данные или другая функция .
  3. Нет петли

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

function totalForArray(arr) {
  // add everything
  return total;  
}

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

// Notice we're accepting two values, the list and the current total
function totalForArray(currentTotal, arr) {
  
  currentTotal += arr[0]; 

  // Note to experienced JavaScript programmers, I'm not using Array.shift on 
  // purpose because we're treating arrays as if they are immutable.
  var remainingList = arr.slice(1);

  // This function calls itself with the remainder of the list, and the 
  // current value of the currentTotal variable
  if(remainingList.length > 0) {
    return totalForArray(currentTotal, remainingList); 
  }
  
  // Unless of course the list is empty, in which case we can just return
  // the currentTotal value.
  else {
    return currentTotal;
  }
}

Слово предостережения: Рекурсия сделает ваши программы более читаемым, и это важно в программировании в функциональном стиле.Тем не менее, в некоторых языках (в том числе JavaScript), вы столкнетесь с проблемами, когда ваша программа делает большое количество рекурсивных вызовов в одной операции (в момент написания, “большой” о 10000 звонков в Chrome, 50000в Firefox и 11000 в Node.js 12 ).Подробности выходят за рамки данной статьи, но суть, что, по крайней мере, до ECMAScript 6 не released 13 , JavaScript не поддерживает то, что называется “ хвост recursion 14 “, который является более эффективным формы рекурсии.Это сложная тема, и не придет очень часто, но это стоит знать .

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

var totalTemp = totalForArray(0, temperatures);

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

function addNumbers(a, b) {
  return a + b;
}

Теперь наша totalForArray функция выглядит следующим образом:

function totalForArray(currentTotal, arr) {
  currentTotal = addNumbers(currentTotal, arr[0]);

  var remainingArr = arr.slice(1);
  
  if(remainingArr.length > 0) {
    return totalForArray(currentTotal, remainingArr);
  }
  else {
    return currentTotal;
  }
}

Отлично!Возвращаясь одно значение из массива является довольно распространенным в функциональном программировании, так что он имеет особое имя, “сокращение”, который вы будете чаще слышать в качестве глагола, как и когда вы “уменьшить массив к единственному значению. “JavaScript имеет специальный метод только для выполнения этой общей задачи.Mozilla Сеть разработчиков обеспечивает полный explanation __25 | 15 , но для наших целей это так просто, как это:

// The reduce method takes a function as its first argument, and that function 
// accepts both the current item in the list and the current total result from 
// whatever calculation you're performing.
var totalTemp = temperatures.reduce(function(previousValue, currentValue){
  // After this calculation is returned, the next currentValue will be 
  // previousValue + currentValue, and the next previousValue will be the 
  // next item in the array.
  return previousValue + currentValue;
});

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

var totalTemp = temperatures.reduce(addNumbers);

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

function totalForArray(arr) {
  return arr.reduce(addNumbers);
}

var totalTemp = totalForArray(temperatures);

Ах, теперь that некоторые читаемый код!Только так вы знаете такие способы, как reduce распространены в самых функциональных языков программирования.Эти вспомогательные методы, которые выполняют действия над массивами вместо зацикливания часто называют “ функции высшего порядка .”

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

function average(total, count) {
  return total / count;
}

Как мы могли бы идти о получении среднего для всего массива

function averageForArray(arr) {
  return average(totalForArray(arr), arr.length);
}

var averageTemp = averageForArray(temperatures);

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

Наконец, мы хотелиполучить одно свойство из массива объектов.Вместо того чтобы показывать вам больше примеров рекурсии, я в погоню и ключ вам на другой встроенный метод JavaScript: map 16 .Этот метод, когда у вас есть массив с одной структуры и должны сопоставить его с другой структурой, например, так:

// The map method takes a single argument, the current item in the list. Check
// out the link above for more complete examples.
var allTemperatures = data.map(function(item) {
  return item.temperatures;
});

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

// Pass in the name of the  ... 

Если вы хотите прочитать полностью статью, посетите сайт наших спонсоров

Comments are closed.