0:17 - Суперпозиция функций 3:05 - Композиция 6:09 - Композиция с любым количеством аргументов / Pipe 8:34 - Композиция любого количества функций 13:14 - Композиция через циклы 17:34 - Композиция через рекурсию 19:50 - Пояснение задания
@marat16895 жыл бұрын
Так приятно открыть для себя ещё один клевый канал по js. Уважуха автору 👍
@voevydskij5 жыл бұрын
Спасибо большое за Ваш труд ) Все доступно и понятно.
@ArMANIAK6663 жыл бұрын
В рекурсивном варианте можно попробовать реверснуть массив и сохранить флаг, что он уже реверснутый, и дальше использовать fns.pop. Даст ли это преимущество перед shift? Насколько я понимаю шифт переписываетвсе значения массива в памяти при каждом вызове (как в деке на С++). Или я не прав? Или преимущество настолько несущественно, что не стоит заморачиваться?
@dimitro.cardellini5 жыл бұрын
Оставлю здесь. Опеределение композиций и пайпов: gist.github.com/DScheglov/9b7a40b76751b09907191f0e1b11bcdc 1) composeSync, pipeSync -- сугубо синхронные (промисы будут пропускать через себя, как обычные аргументы) 2) composeAsyncCb, pipeAsyncCb -- для олд-скульных асинхронных функций (последний аргумент -- это коллбэк) 3) composeAsync, pipeAsync -- для асинхронных (к-е возвращают промисы) и синхронных функций, но результирующая функция всегда Асинхронная. 4) compose, pipe -- тоже самое, что 3), но результирующая функция будет асинхронной, если хотя бы одна входящая -- асинхронная, иначе (если все синхронные), результирующая функция будет синхронной. Может быть в хозяйстве пригодиться. P.S.: @Timur Shemsedinov , для асинхронного пайпинга, асинхронный редьюсинг -- не нужен ;)
@ak1mo84 жыл бұрын
Спасибо, очень интересно! Хотелось бы еще найти примеры кода где применяется композиция в реальных проектах, так сказать, что бы понимать где ее уместно использовать в своих проектах
@TimurShemsedinov4 жыл бұрын
В более сложных лекциях потом найдете множество примеров, например, композиция асинхронных функций
@TheTexPro2 жыл бұрын
Спасибо большое!
@Antonio-fm1sq3 жыл бұрын
Спасибо!
@legioner9mix5 жыл бұрын
подскажите плейлист на канале куда входит это видео
@TimurShemsedinov5 жыл бұрын
Лучше использовать этот индекс github.com/HowProgrammingWorks/Index/blob/master/Courses/Fundamentals.md
@krkaa86633 ай бұрын
Вялiкi дзякуй!
@Андрей-й9ц6я5 жыл бұрын
Спасибо за лекцию. Заметил, что в четвертом примере 11:22 compose можно реализовать через reduceRight вместо reverse в начале. Почти единственный знакомый мне случай, когда можно вставить reduceRight :) В целом с композицией все понятно, кроме момента с обработкой исключений и ошибок (эти два понятия можно разделять, в первом случае программа корректно обрабатывает исключение и продолжает работу, а во втором падает и логирует падение), так вот, как в композиции можно правильно обрабатывать эти сценарии, когда ошибка или исключение произошли где-то по середине и надо, чтобы выполнение пошло по другому пути? В конце вы даете как раз домашнее задание на эту тему, но она не такая и простая как кажется и может будет уместнее применить Either или какие-то другие подходы?
@TimurShemsedinov5 жыл бұрын
Да, отлично, спасибо! Я как-то забыл про reduceRight, в примерах кода на гитхабе исправил: github.com/HowProgrammingWorks/Composition/blob/master/JavaScript/4-multiple.js Да, в классическом функциональном программировании тут можно использовать Maybe, но для JS распространены другие контракты эскалации ошибок из цепочек вычислений: можно сделать это на базе контракта err-back (callback-last / error-first), промисов (или sync/await), можно сделать через события, как я предлагаю в лабораторных (потому, что события уже учили, а вот асинхронное программирование 1 курс еще не освоил).
@Андрей-й9ц6я5 жыл бұрын
@@TimurShemsedinov Благодарю, присмотрюсь повнимательнее к Maybe, видел еще варианты с обработкой ошибок в js в стиле Go, когда функция возвращает массив из значения и ошибки, а они в свою очередь деструктуризируются. Например: const [result, err] = await getSomething(); if (err) { /* handle err */ }
@TimurShemsedinov5 жыл бұрын
@@Андрей-й9ц6я Ну это для синхронных функций нормально и даже удобно потом в другой колбек возвращать callback(...result), но не для async/await, в async/await по контракту нужно делать throw или reject и ловить через .catch или try/catch
@АлександрЧепурнов-э3я4 жыл бұрын
19:25 const compose = (...fns) => x => { if (fns.length === 0) { console.log('never get here') return x;} const fn = fns.pop(); const res = fn(x); if (fns.length === 0) return res; return compose(...fns)(res); }; Объясните, пожалуйста, зачем мы дважды проверяем длину массива, перед рекурсивным вызовом и сразу после? Вроде, достаточно одной проверки...
@ArMANIAK6663 жыл бұрын
Ну, если вопрос еще актуален, то fns.pop() может чытащить последний элемент массива, и тогда вызывать сноча композицию - увеличивать глубину стека, а так уже здесь все ясно-понятно)
@DimitarRad2 жыл бұрын
👌
@DomCobb113 жыл бұрын
спасибо! очень помогло!:)
@ReAgent0034 жыл бұрын
Спасибо за видео! Сложная тема конечно
@masterguyver845 жыл бұрын
Спасибо! А по замеру скорости какие с реализаций самые быстрые? (Цикл, Рекурсия). По идее цикл...
@TimurShemsedinov5 жыл бұрын
Цикл, конечно должен быть существенно быстрее, хотя все нужно проверять
@victormog4 жыл бұрын
Однозначно цикл, и чем больше итераций в рекурсии, тем больше разница.
@ak1mo84 жыл бұрын
11:22 кстати там что бы не делать reverse можно вместо reduce использовать reduceRight
@РобертЗагидуллин-щ1ы5 жыл бұрын
после рефакторинга 5-loop.js примерно на 17 минуте, отпала необходимость в проверке длины аргументов на 0. Цикл просто будет пропущен и вернется 'x' в виде return res. Отправил пулл реквест)
@victorklimov52544 жыл бұрын
Интересно, выражения типа: x => iff(x < 8, console.log, () => {})(x) только мне мозг взрывают?
@TimurShemsedinov4 жыл бұрын
А вот такая реализация EventEmitter: github.com/HowProgrammingWorks/EventEmitter/blob/master/JavaScript/9-min.js
@victorklimov52544 жыл бұрын
@@TimurShemsedinov Да, это очень эстетично! Даже жаль, что так писать нельзя.
@RisDeep4 жыл бұрын
Жаль в лекции не рассмотрены 7-compos~async и 8-compos-proto, может они где-то в следующих лекция встречаются?
@dimitro.cardellini5 жыл бұрын
1:24 -- iff -- в таком виде практически не нужен. Потому, что он ровным счетом используется точно так же, как и тернарка. iff -- это уже композирующая функция: const idX = x => x; const iff = (predicate, thenFn = idX, elseFn = idX) => (...args) => ( predicate(...args) ? thenFn(...args) : esleFn(...args) );
@TimurShemsedinov5 жыл бұрын
Да, но на студентов производит впечатление выражение в кором только функции есть, это код для просветляющего вау-эффекта )))
@dimitro.cardellini5 жыл бұрын
@@TimurShemsedinov так вот в этом случае будет куда круче, когда в компоуз можно будет вставить iif, и арперкейзить или ловеркейзить, если в строке есть магическое слово. Там вообще вау при вау эффект будет. А можно, показать, как без elseFn работает ... Т.е. будет, и композиция, и зверей убивать не надо ) (С) Кот Матроскин
@lb60705 жыл бұрын
хорошо бы было применять теорию к практике то есть показывать обратную связь того сто после выполнения этих функций в интерфейсах (сайт, приложение) получилось
@dimitro.cardellini5 жыл бұрын
Возьмите любой свой код и попробуйте его переписать со следующими ограничениями: 1) используются только функции 2) не используются операторы и методы с сайд-эффектами: (for, while, if, Array.prototype.forEach, etc.). Обратите внимание, что тернарный оператор использовать можно, т.к. он всегда возрващает значение 3) каждая вновь создаваемая функция, либо: делает что-то одно (практически состоит из одного выражения), либо "композирует" другие функции. ----- Посмотрите, что получится. Начните чисто с синхронного кода лучше без циклов, но с условными операторами.
@TimurShemsedinov5 жыл бұрын
Это в отдельных лекциях будет, и уже многое есть. Если теорию с практикой смешивать, то лекции будут по 2-3 часа, я с этого и начинал и оно не способствует усвоению.
@nexgenua5 жыл бұрын
Timur Shemsedinov +++ некоторые 2-х часовые видео уже месяца по 3 держу в закладках, все никак досмотреть не выходит, а по 30 минут +- заходят на ура на одном дыхании.
@victormog4 жыл бұрын
Для тех, кто так же, как и я, не понял сходу этот arrow-function-hell с использованием _reduce()_ массива функций, переписал в "человеческом формате". Может так станет понятнее, как и мне: *const pipe = (...fns) => str => fns.reduce( (v, f) => f(v), str )* const pipe = function(...fns) { // arguments: (fn1, fn2, ...) to array: fns = [fn1, fn2, ...] return function(str) { return fns.reduce( // array.reduce(callback [, initialValue]) // // callback(accumulator, currentValue [, index, array]) function(acc, cur) { // callback, return cur(acc) // cur - current function of array }, // acc - initialValue first time or result of rest str // initialValue ) } } const capitalize = pipe(trim, lower, upperCapital) console.log(capitalize(str))
18:23 -- рекурсия же должна быть хвостовая! ) gist.github.com/DScheglov/b55732b4b3f814a227d75fb6b7d59f2d
@TimurShemsedinov5 жыл бұрын
Не обязательно, в js это ни каких плюсов не дает, из v8 давно удалили оптимизацию хвостовой рекурсии.
@dimitro.cardellini5 жыл бұрын
@@TimurShemsedinov как удалили? Не было и, вдруг, удалили ) Хотя, я, конечно, в проекте ноды не участвовал. Вместе с тем, рекурсии так или иначе лучше делать хвостовыми. Вдруг оптимизацию вернут )
@TimurShemsedinov5 жыл бұрын
@@dimitro.cardellini была, выпилили, а теперь опять хотят добавить, но другиа оптимизации мешают bugs.chromium.org/p/v8/issues/detail?id=4698
@TimurShemsedinov5 жыл бұрын
@@dimitro.cardellini нода тут совсем ни при чем, а по оптимизации хвостовой рекурсии есть отдельная лекция )))
@dimitro.cardellini5 жыл бұрын
@@TimurShemsedinov да) как я мог v8 с нодой перепутать? ) Вообще, почитаю тикет. Сейчас с телефона ... Интересно же, зачем классную штуку убрали
@Denis.Zhelnerovich4 жыл бұрын
через рекурсию можно было бы еще вот так лаконично написать: const pipe = (f, ...rest) => x => f ? pipe(...rest)(f(x)) : x const compose = (...rest) => pipe(...rest.reverse())
@сергейхриптулов-о9щ4 жыл бұрын
Суперпозиция - композиция функций (сложная функция) - это применение одной функции к результату другой. Гипотеза Римана, решение, формула, компьютерная программа. kzbin.info/www/bejne/bp2QhIOnrbmEpZI Квантовая математика - для программирования kzbin.info/door/1nfJPQHSxsdUsrH1Z8k-LA
@victormog4 жыл бұрын
Пол видео объяснять, что функция _compose_ использует аргументы справа налево, а функция _pipe_ - слева направо... странно.
@masterguyver844 жыл бұрын
Для начинающих, оно так!
@victormog4 жыл бұрын
@@masterguyver84 Для начинающих это время потратить бы на разбор _reduce()_ массива функций...
@victormog4 жыл бұрын
const pipe = function(...fns) { // arguments: (fn1, fn2, ...) to array: fns = [fn1, fn2, ...] return function(str) { return fns.reduce( // array.reduce(callback [, initialValue]) // // callback(accumulator, currentValue [, index, array]) function(acc, cur) { // callback, return cur(acc) // cur - current function of array }, // acc - initialValue first time or result of rest str // initialValue ) } } const capitalize = pipe(trim, lower, upperCapital) console.log(capitalize(str))