Три реализации задачи в функциональном стиле

แชร์
ฝัง
  • เผยแพร่เมื่อ 14 ม.ค. 2025

ความคิดเห็น • 172

  • @1FrozenHeart1
    @1FrozenHeart1 3 ปีที่แล้ว +11

    Нравятся такие видосы побольше бы таких

  • @scarlatum
    @scarlatum 3 ปีที่แล้ว +34

    Куплю попугая и назову его "map(tail(arr))(f)(merge(acc)(f(head(arr))))".

    • @АнимусАнанимус
      @АнимусАнанимус 3 ปีที่แล้ว +6

      А он еще и будет периодически кричать "error: a is not iterable" 😂

    • @Uni-Coder
      @Uni-Coder 3 ปีที่แล้ว +1

      Только Илон Маск может давать имена типа X Æ A-12

  • @valbv
    @valbv 3 ปีที่แล้ว +3

    Видос огонь!
    На практике не доводилось работать с функциональным стилем.
    Очень полезно было это узнать

  • @artur1998g
    @artur1998g 3 ปีที่แล้ว +2

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

  • @gloomyrobust
    @gloomyrobust 3 ปีที่แล้ว +3

    Включил видео, отвернулся, через минуту повернулся, экран размыт, ну думаю пора спать.

  • @Жека-к1п
    @Жека-к1п 3 ปีที่แล้ว +24

    История о том, как из JS сделать Common Lisp

    • @Uni-Coder
      @Uni-Coder 3 ปีที่แล้ว

      Теперь надо на JS написать интерпретатор CL, чтобы на нём написать интерпретатор JS :)

    • @Жека-к1п
      @Жека-к1п 3 ปีที่แล้ว

      @@Uni-Coder это проще, чем кажется) С учетом синтаксических особенностей лиспа)

    • @qwertymangames1800
      @qwertymangames1800 4 หลายเดือนก่อน

      Чтобы не писать много скобок уже давно в ФП придумали композицию функций.
      Можно даже свою функцию compose реализовать

  • @MaximRovinsky
    @MaximRovinsky 3 ปีที่แล้ว

    Соер, респект. Это интересный контент. Спасибо 👍🏼

  • @nikolaymatveychuk6145
    @nikolaymatveychuk6145 3 ปีที่แล้ว +4

    Заявленные плюсы звучат очень хорошо, и если сама парадигма написания кода способствует этому - это супер круто. Единственное, что меня не порадовало, это итоговое содержание функции map. Серьёзно, тут же можно полдня только разбирать, что написано в этой строке xD
    Возможно я неправ, говорю строго на правах мнения, но дело в том, что в данном коде присутствует 4 уровня вложенности вызовов, но кроме того цепочка вызовов ещё и зацикливается: мы вызываем map, чтобы получить функцию, в которой вызывается map, чтобы получить функцию, в которой вызывается map, чтобы получить функцию... Может это дело привычки, и в итоге после некоторой практики такое перестаёт вызывать трудности при чтении, но когда видишь такой код впервые, то не можешь отделаться от мысли, что он ужасен :) Чувство приблизительно то же, что и знакомстве с регулярками, которые изначально воспринимаются не иначе как непонятный набор символов, делающий какую-то магию.

    • @drak0an
      @drak0an 3 ปีที่แล้ว +6

      чтобы полюбить рекурсию надо полюбить рекурсию

    • @21POPOV
      @21POPOV 3 ปีที่แล้ว

      Ну есть в ФП ещё "частичное применение функции" и "каррирование" которые помогают вызвать функции более привычно, но в то же время использовать преимущества сокращения арности функции
      Например
      sum(1,3) // 4
      sum(1) // a => a + 1
      То есть можно написать inc = sum(1) - и передавать ее в конвееры, в всякие Монады.

    • @nikolaymatveychuk6145
      @nikolaymatveychuk6145 3 ปีที่แล้ว

      @@21POPOV map = (arr) => (f) => arr.length === 0 ? [] : merge([f(head(arr))])(map(tail(arr))(f));
      Сейчас только подумал, а почему функция не написана так. Я какой-то принцип нарушил, или в видео не оптимально написано (больше вложенность, чем надо)?

  • @sekirogenshiro2210
    @sekirogenshiro2210 3 ปีที่แล้ว +10

    Офигенно"

    • @drak0an
      @drak0an 3 ปีที่แล้ว

      да

  • @antoxatube
    @antoxatube 3 ปีที่แล้ว +11

    тот случай, когда учишь фронтенд и думал, что реакт и редакс сложно))))

  • @nickml5138
    @nickml5138 3 ปีที่แล้ว +3

    В начале видео есть полторы минуты, когда вы просто говорите, можно было, чтобы размытие плавно исчезало перед началом объяснения и плавно возвращалось после, кажется, было бы чуть лучше) А так, спасибо за видео)

  • @yummybunny7351
    @yummybunny7351 3 ปีที่แล้ว +11

    12:30 "... в нормальных языках..." ахахах, бедный JS

    • @bubblesort6368
      @bubblesort6368 3 ปีที่แล้ว +2

      Он нормальный, ноооормальный, - возглас Джигурда)

  • @Bezzil
    @Bezzil 3 ปีที่แล้ว +5

    позновательно, у меня только один вопрос, зачем ?

    • @drak0an
      @drak0an 3 ปีที่แล้ว

      конец видео объясняет же зачем такой изврат

    • @21POPOV
      @21POPOV 3 ปีที่แล้ว

      ФП - для предсказуемости поведения программы, детерминированности выполнения, лёгкости тестирования. Так же помогает корректно обновлять состояние, особенно в многопоточной среде.

    • @eugeneganshin2934
      @eugeneganshin2934 3 ปีที่แล้ว

      @@drak0an хотелось бы увидеть что то реальное, а не инкрементацию значений списка.

  • @rotrhino
    @rotrhino 3 ปีที่แล้ว +3

    Кайф. Как всегда.

  • @vitaliktereshchenko3531
    @vitaliktereshchenko3531 3 ปีที่แล้ว +1

    А не приводит ли это к неоправданому выделению памяти? В каждом вызове рекурсивной функции мы в замыкание ложим новый результат tail() и новый результат marge(), и все они живут пока не розвернется весь стек функции.

    • @gmikay
      @gmikay 3 ปีที่แล้ว +3

      Это абсолютно не важно, главное чтобы код был написан в *функциональном* стиле, память дело десятое

  • @TwilightSun32
    @TwilightSun32 3 ปีที่แล้ว +1

    в третьем примере в реализации pipe надо было sizeOf тоже использовать вместо .length чтобы совсем уж по красоте.
    Но в целом вот этот вот висящий аккумулятор у map немного расстраивает. Если там сделать параметр по умолчанию это нормально будет или против парадигмы? или может переобозвать этот map в некий служебный accMap и его обернуть функцией map где уже не надо будет пихать пустой массив т.к. она будет сама вызывать accMap именно с пустым массивом ? тогда и второй пример бы уже выглядел получше.
    А так немного приходилось ставить на паузу и до пояснений тратить немного времени чтобы понять что да работает, да правильно и как именно. Такие головоломки сами по себе прикольная штука, это было интересно. Ещё видел на жабаскрипте похожую очень по стилю реализацию прикручивания кеширования (мемоизации если угодно) к произвольной функции, тоже хороший пример. Понятное дело что немного практики и к этому всему можно привыкнуть, но наверное лучше это изучать на каком-нибудь хаскеле где это будет естественно а потом уже привносить в js (на codewars кстати есть какое-то количество задач именно по такому принципу - давайте сделаем на js вот такую штуку по примеру хаскеля, достаточно сложные штуки там есть)

    • @АнимусАнанимус
      @АнимусАнанимус 3 ปีที่แล้ว

      Функциональной парадигме не противоречит назвать эту штуку иначе (например flatMapConcat), а map описать как:
      cons map = f => xs => flatMapConcat(xs)(x => [f(x)])([])
      Просто в видео не map. В другой ветке комментариев уже выяснили, что это flatMap с последующим concat :D

    • @TwilightSun32
      @TwilightSun32 3 ปีที่แล้ว +1

      @@АнимусАнанимус кстати да, мап-то ненастоящий

  • @petrvictorovich
    @petrvictorovich 3 ปีที่แล้ว

    Ааа, так все эти композиции из функций - они принципиально работают только с функциями с одним аргументом?

  • @amin--hj8mc
    @amin--hj8mc ปีที่แล้ว

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

  • @CHERNOMORGAMES
    @CHERNOMORGAMES 3 ปีที่แล้ว

    04:30 Так хочется сделать Array.prototype.map = null :)))
    P.S. Про читаемость кода, я понял, что lst это list, а не last, только после того, как было озвучено, что "всё есть список".
    Концепция, на вид, крутая - обязательно попробую.

  • @gMaN124588
    @gMaN124588 3 ปีที่แล้ว

    Есть ощущение, что третья по счету реализация (func_curry.js) - скорее reduce, нежели map. Или я заблуждаюсь?

  • @ФилиппДруан
    @ФилиппДруан 3 ปีที่แล้ว

    Первая задачка, решение на Common Lisp:
    (defun list-inc (lst)
    (if (null lst)
    ()
    (append (list (1+ (car lst)))
    (list-inc (cdr lst)))))

  • @Egorro-h9u
    @Egorro-h9u 3 ปีที่แล้ว +1

    Подобные издательства над js можно пройти на курсах hexlet. Когда решал задачи мозг разрывался.

    • @gMaN124588
      @gMaN124588 3 ปีที่แล้ว

      Я после их курсов проникся ФП и начал писать на Clojure). И да, задачки действительно очень мозголомные.

    • @TheLevius
      @TheLevius 2 ปีที่แล้ว

      это точно ))

  • @ПавелЮлианов
    @ПавелЮлианов 3 ปีที่แล้ว

    Топ!!! Побольше подобного контента. Посоветуйте книгу по ФП.

  • @GogolevDmitry
    @GogolevDmitry 3 ปีที่แล้ว

    Почему во втором примере не сделать функцию incNums
    const incNums = (arr) => map(arr)(a => [a+1])([])
    В этом случае, не будет дополнительной обёртки в виде pipe?

    • @Lex06by
      @Lex06by 3 ปีที่แล้ว +1

      Я думаю потому, что пайп в данном случае является больше целью, если Вы пересмотрите конец видео, то заметите что Соер сказал что "поймёте как с помощью каррированных функций получить пайп", цитата не точная, но смысл такой

  • @АзимАзимов-ч1й
    @АзимАзимов-ч1й 3 ปีที่แล้ว

    🔥🔥🔥🔥🔥

  • @alexandr-v
    @alexandr-v 3 ปีที่แล้ว

    Осталось понять, как это всё понять.

  • @klxqz
    @klxqz 3 ปีที่แล้ว

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

    • @fallenangel1395
      @fallenangel1395 3 ปีที่แล้ว

      О, а можешь, пожалуйста, название подсказать?

    • @ruslanvolovik2745
      @ruslanvolovik2745 3 ปีที่แล้ว

      Как называется?

    • @chillout1943
      @chillout1943 3 ปีที่แล้ว

      @@ruslanvolovik2745 могу предположить, что Functional Programming in Kotlin от manning

  • @itCODE
    @itCODE 3 ปีที่แล้ว

    Всем доброго времени суток. Спасибо за видео, интересный канал. Подписался.
    Начал изучать Java, посмотрим как пойдет. На данный момент пишу на 1С, только без негатива пожалуйста..)
    Всем хорошего просмотра !

    • @Brother_raccoon
      @Brother_raccoon 3 ปีที่แล้ว

      Это не Java а JavaScript это совсем разные языки, общее в них только 4 буквы

  • @АлмазФахрутдинов-м9п
    @АлмазФахрутдинов-м9п 3 ปีที่แล้ว

    бомба

  • @misatokatsuragi9122
    @misatokatsuragi9122 3 ปีที่แล้ว +18

    Первое правило функционального программирования на JS - не использовать JS

  • @eugenenovikov671
    @eugenenovikov671 3 ปีที่แล้ว +3

    очень сложный код, не мой уровень точно

    • @АлексейТимофеев-и4б
      @АлексейТимофеев-и4б 3 ปีที่แล้ว

      На самом деле нет, если есть базовое университетское математическое образование. Что как говорилось неоднократно необходимо для работы в it

    • @eugenenovikov671
      @eugenenovikov671 3 ปีที่แล้ว

      Я и без вышки по математике ответы от сервера маплю, просто тут спагетти плюс хаскель какой-то. Для системного программиста норм, мне как фронту спагетти

  • @eugeneganshin2934
    @eugeneganshin2934 3 ปีที่แล้ว

    Эх, столько нужно выучить чтобы посчитать список чисел) Пойду лучше на яве покодю.

  • @leshiq4214
    @leshiq4214 3 ปีที่แล้ว +1

    Умные люди, подскажите, пожалуйста, в каких случаях функциональный стиль программирования эффективнее/выгоднее других? А также, кроме красоты, зачем юзать map, если можно перебрать методом forEach или циклом for?

    • @КаримАль-Савади
      @КаримАль-Савади 3 ปีที่แล้ว +2

      В многопоточности, например.

    • @fALE36484
      @fALE36484 3 ปีที่แล้ว +2

      Map и forEach решают разные же задачи)

    • @vgamzatov
      @vgamzatov 3 ปีที่แล้ว +1

      строгий ответ таков:
      есть данность а есть заданность. То есть статускво и вектор развития.. Вопросы эффективностидолжны быть не писателя кода вопросами а вопросами писателя компиляторов и разработчиков железа (что и происходит на самом деле если смотреть на бигпикчу эволюции языков). Вопросами писателей кода должна быть логическая строгость со всеми вытекающими из строгости профитами (безопасность, отказоустойчивость. масштабируемость и тд - перечислять можно бескконечно).
      А теперь ответ конкретнее:
      >> в каких случаях функциональный стиль программирования эффективнее/выгоднее других?
      ДОЛЖЕН быть эффективнее любых других. Если это (пока!) не так - это не программиста проблемы, - проблемы компиляторов и железа.
      И каждый должен заниматься своим делом и стремиться к идеалу при этом

    • @АнимусАнанимус
      @АнимусАнанимус 3 ปีที่แล้ว

      В дополнение к другим ответам:
      "constraints liberate, liberties constrain"
      map ограничивает возможности того, что можно сделать с массивом. Значит, читая код и видя map, мы уже точно знаем многое о том, что там происходит. В частности, что длина результирующего массива не изменилась, и что значение следующего элемента изменяется не в зависимости от предыдущего (ну, в js этого свойства нет, ибо map корявенький).
      Все эти вещи позволяют читать меньше кода (не говоря уж о том, что циклы обычно многословнее).
      Например, если ты ищешь багу, в результате которой список из функции возвращается короче, чем должен быть, то встретив цикл, его придется читать. А встретив map - не придется.

    • @bdick8136
      @bdick8136 3 ปีที่แล้ว

      @@КаримАль-Савади очень сомнительное преимущество.

  • @MrVintarb
    @MrVintarb 3 ปีที่แล้ว +8

    Только всё будет тормозить)

    • @rotrhino
      @rotrhino 3 ปีที่แล้ว

      Почему же?

    • @HannibalLecter-w3r
      @HannibalLecter-w3r 3 ปีที่แล้ว +4

      @@rotrhino потому что мы копируем массив

    • @MrVintarb
      @MrVintarb 3 ปีที่แล้ว +5

      Каждый рекурсивный вызов в данных примерах создаёт массив.
      Это далеко не бесплатная операция.

    • @pepsirusso
      @pepsirusso 3 ปีที่แล้ว +1

      @@MrVintarb фанатам ФП это неинтересно

    • @АнимусАнанимус
      @АнимусАнанимус 3 ปีที่แล้ว

      Это проблемы js-а уже😏

  • @sekirogenshiro2210
    @sekirogenshiro2210 3 ปีที่แล้ว

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

  • @daniilboiko
    @daniilboiko 3 ปีที่แล้ว +2

    Без паттерн матчинга выглядит не очень )))

    • @АнимусАнанимус
      @АнимусАнанимус 3 ปีที่แล้ว

      Соглы. Но если паттернматчить по Чёрчу, то не будет оптимизации хвостовой рекурсии :(
      const destroyArray = ifEmpty => ifCons => arr =>
      arr.length === 0 ? ifEmpty : ifCons(head(arr))(tail(arr))
      const map = f => destroyArray ([])(x => xs => cons(f(x))(map(f)(xs)))

    • @АнимусАнанимус
      @АнимусАнанимус 3 ปีที่แล้ว

      Кстати, самое "мясо" Соер решил не показывать. Это списки в кодировке Чёрча:
      const Empty = ifEmpty => ifCons => ifEmpty
      const Cons = x => xs => ifEmpty => ifCons => ifCons(x)(xs)
      const toArray = xs => xs ([])(y => ys => [y,...toArray(ys)])
      const fromArray = xs => xs.reverse().reduce((ys,y) => Cons(y)(ys), Empty)
      const foldl = f => acc => xs =>
      xs(acc)(y => ys => foldl(f)(f(acc)(y))(ys))
      const map = f => xs =>
      xs(Empty)(y => ys => Cons(f(y))(map(f)(ys)))
      let myList = Cons(1)(Cons(2)(Cons(3)(Empty)))
      Хотя это не кажется таким хардкорным, как тот безумный map в конце видео :D

  • @THEGhost902
    @THEGhost902 3 ปีที่แล้ว +1

    Это конечно круто и очень интересно, но с точки зрения производительности в js просто ужас

    • @Brother_raccoon
      @Brother_raccoon 3 ปีที่แล้ว

      А почему?

    • @eugeneganshin2934
      @eugeneganshin2934 3 ปีที่แล้ว

      @@Brother_raccoon ну дак стек не резиновый

  • @channeldsr9983
    @channeldsr9983 3 ปีที่แล้ว +1

    То есть ради удобства написания функции мы тащим особенности во вне?
    Я ожидаю, что a => [a + 1] вернет все-таки массив, но из-за реализации, удобной чуваку, который ее писал, а не мне, придется забивать себе голову особенностями использования.

    • @АнимусАнанимус
      @АнимусАнанимус 3 ปีที่แล้ว

      a => [a + 1] ээто выражение типа 'number => Array', и эта лямбда, получив какую-то жлыгу, вернет массив, не иначе.
      Но мы передаем ее в качестве аргумента в функцию next, а вот next приняв ее, вернет функцию типа 'Array => Array'.
      Реализация чего-то-там тут не при чем.

  • @gogenmogen3562
    @gogenmogen3562 3 ปีที่แล้ว +14

    А тепреь вспомните что в императивном стиле достаточно написать
    for (let i = 0; i < arr.length; i++) arr[i]++;
    что будет работать куда быстрее, чем рекурсивная функция, бесконечно создающая новый массив.
    Фп удобно, когда нам нужно сказать не только, что сделать, но еще и сказать, как сделать.
    Но в абсолют это возводить не стоит.
    А Соер тем временем стал фп-сектантом и поехал кукухой(

    • @vgamzatov
      @vgamzatov 3 ปีที่แล้ว +2

      У Соера на канале акцент на философию - чем он своеобразен и интересен. Я думаю я не один такой ценитель поехавших кукух ;)

    • @СергейНовожилов-я6я
      @СергейНовожилов-я6я 3 ปีที่แล้ว

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

    • @АнимусАнанимус
      @АнимусАнанимус 3 ปีที่แล้ว

      Ну да,
      for (let i = 0; i < arr.length; i++) arr[i]++;
      ведь легче читать и поддерживать, чем
      arr.map(x => x + 1)
      И кто здесь сектант-то? ':)

    • @gogenmogen3562
      @gogenmogen3562 3 ปีที่แล้ว +1

      ​@@АнимусАнанимус Конечно обычный мап легче читается и поддерживается, тут соглашусь.
      Проблема была в том, что обычный фор был превращен извините хуй знает во что.

    • @gogenmogen3562
      @gogenmogen3562 3 ปีที่แล้ว

      @@СергейНовожилов-я6я Может быть полезно, безусловно. Но все таки создание массива каждую итераю лишь для абстракции, куча (((((((((скобочек))))))))) (мы что, превращаем жс в лисп?).
      И прочее отталкивает меня от класического фп, слишком уродливо, хоть и "самодоказуемо".
      Не нужно делать из петуха корову, если вам нужно молоко - корову и возьмите

  • @goosedb4470
    @goosedb4470 3 ปีที่แล้ว +4

    непонятно, почему map стал каким-то убогим редюсом. ну и вообще кашу какую-то понаписал.

    • @АнимусАнанимус
      @АнимусАнанимус 3 ปีที่แล้ว +3

      Это, конечно, не map, но и не reduce:
      если перевести дословно (но с паттерн матчингом) на хачкель (исправив ошибку с merge, которая у Соера конкатенирует списки, а должна соединять голову с хвостом):
      map [] _ acc = acc
      map (x:xs) f acc = map xs f (f x : acc)
      или если выразить через настоящий (труЪ) map:
      soerMap as f bs = reverse (map f as) ++ bs
      Хотя конечно, это прям совсем далеко от настоящего map ':)
      map (+5) [0..3] == [5,6,7,8]
      soerMap [0..3] (+5) [10..13] == [8,7,6,5,10,11,12,13]

    • @nikolaymatveychuk6145
      @nikolaymatveychuk6145 3 ปีที่แล้ว +1

      @@АнимусАнанимус стесняюсь спросить... но надо... :) Это я так плохо шарю в синтаксисе js, или это на каком-то другом языке написано, с которым я незнаком? Если на другом, то подскажите на каком, пожалуйста. Появилось ощущение, что я хочу знать этот язык :)

    • @АнимусАнанимус
      @АнимусАнанимус 3 ปีที่แล้ว +1

      @@nikolaymatveychuk6145 это Haskell :)

    • @nikolaymatveychuk6145
      @nikolaymatveychuk6145 3 ปีที่แล้ว +1

      @@АнимусАнанимус спасибо

    • @S0ERDEVS
      @S0ERDEVS  3 ปีที่แล้ว +1

      ​@@АнимусАнанимусну че ты придумываешь? Хоть код бы запустил, что-ли.
      Ты либо пиши опровержение на языке первоначального примера, либо корректно переводи. А так получается, что ты приводишь пример некорректно переведенный с JS и говоришь что это "совсем не то", конечно не то, ведь ты неправильно перевел. ))))
      твой пример: map(+5) [0..3] == [5, 6, 7, 8]
      мой пример: map([0,1,2,3])(a => [a + 5])([]) == [5, 6, 7, 8]
      можно поспорить насчет аккумулятора, но в том, что это не map, нужны какие-то доводы, я их не увидел.

  • @kodaf
    @kodaf 3 ปีที่แล้ว +2

    Это конечно прикольно, но бесполезно
    Жду тухлые помидоры

  • @Slava_tobi_Ukraine
    @Slava_tobi_Ukraine 3 ปีที่แล้ว +2

    А можно без размытия экрана? Раздражает