у меня много пет-проджектов и для каждого нужно настроить минимальную сборку
для книжки по функциональному программированию тоже захотелось иметь среду выполнения
конечно же create-react-app для этого случая слишком мощен (да и местный линтер меня раздражает), так что я взяла парсель и накрутила минимальной функциональности. В данном случае это — еслинт, рамбда и лоудаш
и всё бы хорошо, но вс код из коробки не умеет в динамические импорты, а без динамических импортов хочется только упасть и лежать. За них отвечает
так что я написала небольшую заметчк:
https://medium.com/@twanttobealighi/%D0%BA%D0%B0%D0%BA-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B8%D1%82%D1%8C-%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5-%D0%B8%D0%BC%D0%BF%D0%BE%D1%80%D1%82%D1%8B-%D1%87%D0%B5%D1%80%D0%B5%D0%B7-babel-ceebc0bc7361
для книжки по функциональному программированию тоже захотелось иметь среду выполнения
конечно же create-react-app для этого случая слишком мощен (да и местный линтер меня раздражает), так что я взяла парсель и накрутила минимальной функциональности. В данном случае это — еслинт, рамбда и лоудаш
и всё бы хорошо, но вс код из коробки не умеет в динамические импорты, а без динамических импортов хочется только упасть и лежать. За них отвечает
babel со своими миллионами плагинов, которые с первого раза никогда не работаюттак что я написала небольшую заметчк:
https://medium.com/@twanttobealighi/%D0%BA%D0%B0%D0%BA-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B8%D1%82%D1%8C-%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5-%D0%B8%D0%BC%D0%BF%D0%BE%D1%80%D1%82%D1%8B-%D1%87%D0%B5%D1%80%D0%B5%D0%B7-babel-ceebc0bc7361
Medium
Как настроить динамические импорты через babel
Устанавливаем зависимости
функция
обязательно нужно вернуть результат через
chain из lodash
позволяет применить много функций сразу для одного значения. каждой следующей функции передаёт результат предыдущейобязательно нужно вернуть результат через
.value()
пример:_.chain('mememe')
.capitalize()
.value();
//Mememe
пример посложнее:_.chain([36, 40, 1, 3, 1, 1, 1, 1])тут важно заметить, что uniq это тоже лоудашевская функция, доступная внутри
.sort((a, b) => a - b)
.uniq()
.value();
// [1, 3, 36, 40]
chain без _функция высшего порядка это функция, которая в качестве аргументов принимает другие функции или возвращает функцию в качестве результата
например
например
onEventListenerbutton.addEventListener("click", function() {
//do stuff
})декоратор это функция, которая расширяет функционал переданной ей функции
пример:
пример:
hoc — функция, которая принимает компонент и возвращает новый компонент с расширенным функционалом
то есть hoc это частный случай декоратора
https://reactjs.org/docs/higher-order-components.html
то есть hoc это частный случай декоратора
https://reactjs.org/docs/higher-order-components.html
legacy.reactjs.org
Higher-Order Components – React
A JavaScript library for building user interfaces
вернёмся к фп
преимущество такой колбасы в том, что мы избегаем циклов и создания переменных — повышаем читаемость и сокращаем количество мест в которых можем ошибиться
_.chain(persons)
.filter(isValid)
.map(_.property('address.country'))
.reduce(gatherStats, {})
.values()
.sortBy('count')
.reverse()
.first()
.value()
.name; //-> 'US'
преимущество такой колбасы в том, что мы избегаем циклов и создания переменных — повышаем читаемость и сокращаем количество мест в которых можем ошибиться
в
_.chain ничего не выполняется, пока не будет вызвана функция value() — где-то здесь и начинаются отложенные вычисления_.mixin позволяет добавлять в лоудашевский (не только) объект свои методыпример
_.mixin({
test: () => 'hello world',
});
const res = _.test();
console.log(res);
// hello worldобратим внимание на вот такой объект примеси:
_.mixin({
select: _.map,
from: _.chain,
where: _.filter,
sortBy: _.sortByOrder,
});
он делает js-код похожим на sql-запрос_.from(persons)sql супир
.where(p => p.birthYear > 1903 && p.address.country !== 'US')
.sortBy(['firstname'])
.select(p => p.firstname)
.value();
Рекурсия
Понять рекурсию несложно, нужно научиться мыслить рекурсивно
вот простая рекурсивная функция:
в нашем случае вот оно:
но есть способы это оптимизировать, ето я узнаю только в седьмой главе (сейчас я на третьей)
Понять рекурсию несложно, нужно научиться мыслить рекурсивно
вот простая рекурсивная функция:
function sum(arr) {
if(_.isEmpty(arr)) {
return 0;
}
return _.first(arr) + sum(_.rest(arr));
}
sum([]); //-> 0
sum([1,2,3,4]);
у неё есть базовая ветвь или условие возвратав нашем случае вот оно:
if(_.isEmpty(arr)) {
return 0;
}
рекурсивная функция вызывает сама себя, и сохраняет все эти вызовы во внутреннем стеке контекстов выполнения. И только когда алгоритм достигнет условия возврата, выполнятся вложенные вызовы1 + sum[2,3,4]из-за множества вложенных контекстов, с производительностью у рекурсии не очень
1 + 2 + sum[3,4]
1 + 2 + 3 + sum[4]
1 + 2 + 3 + 4 + sum[]
1 + 2 + 3 + 4 -> halts, stack unwinds
1 + 2 + 7
1 + 9
10
но есть способы это оптимизировать, ето я узнаю только в седьмой главе (сейчас я на третьей)
ирл рекурсия чаще всего используется чтобы выпендриться на собеседовании или обойти древовидную структуру данных (дом-дерево например)
дальше в книжке идёт несколько длинных примеров кода создания древовидной структуры и методов её обхода
главное что стоит запомнить:
- в родительском узле есть дети, а у детей есть ссылки на родителей
- в этом случае мы обходим дерево в ширину (а можно ещё и в глубину или рандомно или еще как-то)
дальше в книжке идёт несколько длинных примеров кода создания древовидной структуры и методов её обхода
главное что стоит запомнить:
- в родительском узле есть дети, а у детей есть ссылки на родителей
- в этом случае мы обходим дерево в ширину (а можно ещё и в глубину или рандомно или еще как-то)
условие возврата тут находится в строке 17 —
изначально дерево ето
строку 8 можно пропустить
дальше в строке 12 мы смотрим, есть ли у ноды дети и если есть то мы рекурсивно вызываем эту же функцию на детях и детях детей.
и после детей второго уровня возвращаемся к детям первого уровня и проверяем их
и когда все дети проверены и у текущей ноды нет детей мы возвращаем дерево
return treeизначально дерево ето
null так что мы его создаём с переданной снаружи нодойстроку 8 можно пропустить
дальше в строке 12 мы смотрим, есть ли у ноды дети и если есть то мы рекурсивно вызываем эту же функцию на детях и детях детей.
и после детей второго уровня возвращаемся к детям первого уровня и проверяем их
и когда все дети проверены и у текущей ноды нет детей мы возвращаем дерево
это всё довольно запутано, но доступно для понимания при троганьи руками и консоль.логами
при желании трогать можно здесь:
https://livebook.manning.com/book/functional-programming-in-javascript/chapter-3/193
при желании трогать можно здесь:
https://livebook.manning.com/book/functional-programming-in-javascript/chapter-3/193
Композиция функций
Это процесс группирования сложного поведения, разделенного на простые задачи
Главное преимущество — отделение описания функции от её вычисления
например
Данная программа начнет вычисляться только когда произойдет вызов функции
Это процесс группирования сложного поведения, разделенного на простые задачи
Главное преимущество — отделение описания функции от её вычисления
например
const str = `We can only see a short distance ahead but we can see plenty there that needs to be done`;
const explode = (str) => str.split(/\s+/);
const count = (arr) => arr.length;
const countWords = R.compose(count, explode);
Данная программа начнет вычисляться только когда произойдет вызов функции
countWords