Ayub Begimkulov - уроки по JS
3.11K subscribers
29 photos
212 links
По вопросам и деловым предложениям писать на @ayub_begimkulov
Download Telegram
Пока компилируется проект, реши написать еще один пост по наболевшей теме на ревью и в целом, во многих проектах.

Это тема касающаяся функционального программирования. Наверное многие из вас знают хайп вокруг функционального программирования, чистых функций и immutable data structures.

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

Приведу пример кода:


const stickyRows = Object.entries(this.props.stickyRows || {})
.map(([start, end]) => [parseInt(start, 10), end])
.filter(([start, end]) => {
return start < lastRow && (!end || end >= lastRow);
})
.map(([index]) => index);


Кажется, все написано, как нужно - нету мутаций, все функции чистые, все по канонам ФП.

Но давайте посмотрим на этот код с другой стороны…


Object.entries - O(n) память, O(n) cpu.
map - O(n) память, O(n) cpu, а тут их еще 2.
filter - тоже самое.


В сумме, у нас выходит 4 итерации и 4 массива, 3 из которых будут собраны сборщиком мусора!

Можно написать тот же самый код в “императивном” стиле, и получить 1-у итерацию и 0 лишних массивов.


const stickyRowsArray: number[] = [];

for (const key in stickyRowsMap) {
if (!hasOwn(stickyRowsMap, key)) {
continue;
}

const start = parseInt(key);
const end = stickyRowsMap[key];

const isInRange = start < lastRow && (!end || end >= lastRow);

if (!isInRange) {
continue;
}

stickyRowsArray.push(start);
}


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

Да и работать будет в разы быстрее. Есть примеры еще более странные, но часто такое можно увидеть от новичков:


function flattenOne(arrays) {
return arrays.reduce((result, array) => result.concat(array), []);
}


Если вдруг кто не знает concat - immutable метод, который объединяет 2 массива в один. В таком случае у нас вообще будет кубическое время и память. O((N^2+2MN)/2), если быть точным, где M - размер вложенных массивов, а N - размер arrays.

И к тому же, в данном случае result.push никак не испортил бы иммутабельность функции flattenOne. reduce создает полностью новый массив, переданный в параметр массив тоже arrays никак не мутируется.

В итоге, мутация у нас есть только внутри функции, где код полностью под нашим контролем. В таких НОРМАЛЬНО и даже НУЖНО использовать мутирующие методы.

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

Вот такие дела.

#devtips #fp #react
19👍10🔥1💯1🍓1
Всем привет!

Сегодня хочу поделиться одной интересной статьей, которую я впервые прочитал где-то 3 года назад, когда вникал в функциональное программирование.

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

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

В общем, советую всем почитать.

https://www.digitalocean.com/community/tutorials/javascript-functional-programming-explained-fusion-transduction

#devtips #fp
👍172🎉1💯1🍓1