code_notes
71 subscribers
136 photos
1 video
134 links
учусь делать веб

обратная связь: t.me/dmorenogogoleva
Download Telegram
вернёмся к фп

_.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)
.where(p => p.birthYear > 1903 && p.address.country !== 'US')
.sortBy(['firstname'])
.select(p => p.firstname)
.value();


sql супир
Рекурсия

Понять рекурсию несложно, нужно научиться мыслить рекурсивно

вот простая рекурсивная функция:
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 — return tree

изначально дерево ето null так что мы его создаём с переданной снаружи нодой
строку 8 можно пропустить

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

и когда все дети проверены и у текущей ноды нет детей мы возвращаем дерево
это всё довольно запутано, но доступно для понимания при троганьи руками и консоль.логами

при желании трогать можно здесь:
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
пример:
самое сложное тут — функции выполняются снизу вверх
напротив каждой я написала результат выполнения, так что в целом всё понятно
чтобы выполнять функции в привычном порядке, можно использовать не compose, а pipe
(ура)
Композиция функий побуждает к бесточечному стилю программирования
(он еще называется комбинаторным)
Термин ссылочная прозрачность означает, что мы можем заменить функцию результатом её выполнения

Функция half(x) принимает число x и возвращает значение половины x. Если мы передадим этой функции аргумент 8, она вернет 4. После вызова чистая функция всегда может быть заменена результатом своей работы. Например, мы могли бы заменить half(8) на 4: где бы эта функция не использовалась в нашем коде, подмена никак не повлияла бы на конечный результат.

https://medium.com/devschacht/glossary-of-modern-javascript-concepts-1198b24e8f56
если функция неизменно возвращает один и тот же результат для одних и тех же передаваемых ей входных значений, она обладает ссылочной прозрачностью.
Монады

Монада это проектный шаблон, применяемый для описания вычислений в виде последовательности стадий, где вообще неизвестно обрабатываемое значение

Сами монады абстрактны и лишены всякого реального смысла. Их истинный потенциал начинает раскрываться только после того, как они будут реализованы в виде конкретного типа данных