На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: ElcnU, ANDLL, fatalist
  
> Изучаю Haskell
    Здрасте!

    начал изучать Haskell :D
    вот пытаюсь перевести на JS код с Haskell но тока в функциональном стиле JS
    ExpandedWrap disabled
      nouns = ["frog","raven","ribbit"]
      adjectives = ["lazy","angry","tiny","happy","shy"]
      mixin nouns adjectives = [adj ++ " " ++ noun | adj <– adjectives, noun <– nouns]

    Выхлоп
    ExpandedWrap disabled
      [ "lazy frog","angry frog","tiny frog","happy frog","shy frog",
      "lazy raven","angry raven","tiny raven","happy raven","shy raven",
      "lazy ribbit","angry ribbit","tiny ribbit","happy ribbit","shy ribbit" ]


    Пробую через Array,reduce, пока стена :wall:
      Сам порешал :D
      ExpandedWrap disabled
        function mixin(nouns, adjs) {
            return nouns.reduce((a, noun) => {
              const v = adjs.map(adj => {
                return adj + ' ' + noun;
              });
              return [...a, ...v];
            }, []);
        }


      На хаскелле как то более проще думать такие задачи, лямбда исчисление рулит! :whistle:

      Haskell:
      ExpandedWrap disabled
        mixin nouns adjs = [adj ++ " " ++ noun | adj <– adjs, noun <– nouns]

      Так изменил в более функциональный стиль JS, но все равно не так очевидно как на Хаскеле :D
      ExpandedWrap disabled
        const mixin = (nouns, adjs) => nouns.reduce((a, noun) => [...a, ...adjs.map(adj => adj + ' ' + noun)], []);
      Сообщение отредактировано: Cfon -
        Продолжаю изучать удивительный Haskell! :D
        Еще одна задачка на поиск прямоугольных треугольников, дано три списка с числами от 1 до 10 например, надо найти все совпадения прямоугольных треугольников. На хаскеле изи! :D
        ExpandedWrap disabled
          aa =[1..10]
          bb = [1..10]
          cc = [1..10]
          triples aa bb cc = [(a,b,c) | a <- aa, b <- bb, c <- cc, a^2 + b^2 == c^2]

        Выхлоп
        ExpandedWrap disabled
          [(4,3,5),(3,4,5),(8,6,10),(6,8,10)]

        Как теперь это на JS написать? :wacko:

        Добавлено
        Переключил моск с функционального на императивный режим :lool:
        Оказывается тут идет тупой перебор по трем циклам :D
        ExpandedWrap disabled
          const aa = [1,2,3,4,5,6,7,8,9,10];
          const bb = [1,2,3,4,5,6,7,8,9,10];
          const cc = [1,2,3,4,5,6,7,8,9,10];
           
          function triples(aa, bb, cc) {
            var v=[];
            aa.forEach(a => {
              bb.forEach(b => {
                cc.forEach(c => {
                  if ((a*a + b*b) === c*c) {
                    v.push([a,b,c]);
                  }
                });
              });
            });
            return v;
          }
        Сообщение отредактировано: Cfon -
          Одно замечание по коду, в Хаскеле все функции автоматически каррируются :D
          на JS это будет выглядеть так
          ExpandedWrap disabled
            // Каррированная версия triples
            function triples(aa) {
              return bb => {
                return cc => {
                  var v = [];
                  aa.forEach(a => {
                    bb.forEach(b => {
                      cc.forEach(c => {
                        if ((a*a + b*b) === c*c) {
                          v.push([a,b,c]);
                        }
                      });
                    });
                  });
                  return v;
                };
              };
            }
             
            triples(aa)(bb)(cc);

          зачем Хаскель это делает? :blink:
          да хз я еще не дошел до этого... вроде бы это связано с его реализацией, а именно лямбда функциями :unsure:
          в данном коде на JS это делать не обязательно :D
          Сообщение отредактировано: Cfon -
            Разобрался зачем :D
            Для того чтобы юзать их в функциях высшего порядка, например
            ExpandedWrap disabled
              const result = [[1,2,3,4,5],[6,7,8,9,10]].map(triples(aa)(bb));
              console.log(result);
              // [[[ 3, 4, 5 ]], [[ 6, 8, 10 ]]]


            ну а на Haskell все проще :D
            ExpandedWrap disabled
              map (triples aa bb) [[1..5],[6..10]]
              // [[(3,4,5)],[(6,8,10)]]


            Кто не понял объясняю, каррированная функция передается функции высшего порядка путем частичного применения :blush:

            Добавлено
            Очередной вопрос, вот на Haskell код так называемой быстрой сортировки
            ExpandedWrap disabled
              quicksort [] = []
              quicksort (x : xs) =
                  quicksort [a | a <- xs, a <= x] ++
                  [x] ++
                  quicksort [a | a <- xs, a > x]


            как его переделать на JS :wacko:
            Сообщение отредактировано: Cfon -
              Вот вам функционально-подобная попытка на JS приблизится к великому Хаскеллу :D
              ExpandedWrap disabled
                function quicksort(array) {
                    if (array.length === 0) return [];
                    
                    const origin = [...array];
                    const elem0 = origin.pop();
                    const left = origin.filter(elem => elem < elem0);
                    const right = origin.filter(elem => elem >= elem0);
                 
                    return [...quicksort(left), elem0, ...quicksort(right)];
                }
                 
                var nums = [10,2,5,3,1,6,7,4,2,3,4,8,9];
                var sortedNums = quicksort(nums);
                console.log(nuts);       // [ 10, 2, 5, 3, 1, 6, 7, 4, 2, 3, 4, 8, 9 ]
                console.log(sortedNums); // [ 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 10 ]


              И все равно императивный стиль JS присутствует :D
              Сообщение отредактировано: Cfon -
                Для евангелистов reduce коим являюсь сам :D, вот более оптимизированая версия за счет одного цикла, вместо двух в случае с filter:
                ExpandedWrap disabled
                  function quicksort(array) {
                      if (array.length === 0) return [];
                      
                      const origin = [...array];
                      const elem0 = origin.pop();
                   
                      var res = origin.reduce((aa, elem) => (
                          (elem < elem0)
                              ? [[...aa[0], elem], aa[1]]
                              : [aa[0], [...aa[1], elem]]
                      ), [[],[]]);
                      
                      return [...quicksort(res[0]), elem0, ...quicksort(res[1])];
                  }

                Цикла? :facepalm:
                Да-да не удивляйтесь! В JS все равно надо переключаться в императивный режим :jokingly:
                Сообщение отредактировано: Cfon -
                  Продолжаю переносить задачки из Хаскель на JS :D

                  вот исходная задачка на удаление определенного числа элементов из списка с использованием рекусии:
                  ExpandedWrap disabled
                    drop 0 xs = xs
                    drop _ [] = []
                    drop n (x:xs) = drop (n-1) xs

                  а вот та же но через foldl (это аналог reduce в JS)
                  ExpandedWrap disabled
                    drop 0 xs = xs
                    drop _ [] = []
                    drop n xs = foldl (\xs _ -> tail xs) xs [1..n]

                  С рекурсией на JS не было проблем
                  ExpandedWrap disabled
                    function drop(n, array) {
                        if (n === 0) return array;
                        if (array.length == 0) return [];
                        
                        array.shift();
                        return drop(n-1, array);
                    }
                     
                    drop(1, [1,2,3]) // [2,3]

                  а вот как сделать тоже но через reduce? :wacko:

                  Небольшая поправочка в Хаскелле все данные иммутабельны, а у меня тут исходный массив array меняется, что не в Хаскел-стиле! Правим:
                  ExpandedWrap disabled
                    function drop(n, array) {
                        const origin = [...array];
                        if (n === 0) return origin;
                        if (array.length == 0) return [];
                        
                        origin.shift();
                        return drop(n-1, origin);
                    }
                  Сообщение отредактировано: Cfon -
                    :lool: ВСЕ ПРОСТО!! я забыл что в JS можно изменять состояние, это ж не Хаскель :facepalm:
                    Мде сложно переключаться с функционального на императивный режим, надо тернироваться :D
                    Вот решение, получается еще проще чем в Хаскелле
                    ExpandedWrap disabled
                      function drop(n, array) {
                          if (n === 0) return array;
                          if (array.length == 0) return [];
                       
                          return array.reduce((accum, elem) =>
                              (n-- > 0) ? accum : [...accum, elem], //<--- ВОТ ТУТ ИЗМЕНЯЕМ n.
                          []);
                      }

                    или через filter еще проще :D
                    ExpandedWrap disabled
                      function drop(n, array) {
                          if (n === 0) return array;
                          if (array.length == 0) return [];
                          
                          return array.filter(() => (n-- <= 0));
                      }

                    да и начальные условия тут тоже можно опустить :D
                    ExpandedWrap disabled
                      function drop(n, array) {  
                          return array.filter(() => (n-- <= 0));
                      }


                    Хотя я погорячился сказав что проще Хаскеля не проще! куда ж еще проще? :blink:
                    ExpandedWrap disabled
                      drop n xs = foldl (\(_:xs) _ -> xs) xs [1..n]


                    Да в JS уже есть функция удаления splice, но моя цель перевести с Haskell на JS в функциональном стиле, хотя в предыдущих вариантах был применен полу императивный стиль, а не фунциональный и решение в Haskell стиле требует еще покумекать :scratch:
                    ну т.е. сделать без мутации переменной n.
                    Сообщение отредактировано: Cfon -
                      Так так так... ща рожу... а не показалось :lool:
                        .... иииии! родил зверюшку! :lool:
                        ExpandedWrap disabled
                          function drop(n, array) {
                              const v = [...Array(n)].map((_,n) => n + 1);
                              return v.reduce(xs => {
                                  xs.shift();
                                  return xs;
                              }, [...array]);
                          }

                        Объясняю что тут происходит. Я не сразу допедрил как можно это решить без мутации n! :wall:
                        Сила императивного стиля моск реально морозит :D но после долгих насилований себя я прозрел! :jokingly:

                        если внимательно посмотреть на код Хаскелля видно что он просто производит свертку по числовому списку, а не по целевому списку! Вот где фокус то был! :blink:
                        Ну а дальше дело техники, генерирую массив чисел от 1 до n поскольку в JS нет встроенного генератора массива как в Хаскелле и далее делаю свертку хотя это на самом деле не свертка, а простая мутация исходного массива путем выкидывания лишних элементов :D
                        Все тоже можно было сделать тупо в цикле, но мне хотелось приблизить код к Хаскел-стилю, ну те. к функциональному стилю :blush:

                        Немного видоизменил код чтобы максимально приблизится к Haskell:
                        ExpandedWrap disabled
                          const genN = n => [...Array(n).map((_, n) => n + 1)];
                          const drop = (n, xs) => genN(n).reduce(xs => (xs.shift(), xs), [...xs]);

                        Вроде бы уже похоже на функциональный стиль :D
                        Сообщение отредактировано: Cfon -
                          Реализация drop через свертку исходного списка
                          ExpandedWrap disabled
                            drop n xs = fst $ foldr f z xs
                              where
                                f x (xs, m) | m > 0 = (x:xs, m-1)
                                f _ (xs, _) = (xs,0)
                                z = ([], m)
                                m = length xs - n

                          получилось длиннее, но более понятно :D

                          теперь надо перевести на JS :blink:

                          OK. будем думать.

                          ПС. в последнее время я стал адептом краткой нотации :D
                          Сообщение отредактировано: Cfon -
                            Готово! Максимально приближенный Хаскель-стиль :blush:
                            ExpandedWrap disabled
                              const drop = (n, xs) => (
                                  xs.reduceRight(({xs, m}, x) => (
                                      (m > 0) ? (xs.unshift(x), {xs, m: m-1}) : {xs, m:0}
                                  ), {xs:[], m: xs.length - n}).xs
                              );

                            Нравится мне эта шифрограмма! :D
                              Продолжаем, на очереди dropWhile, его суть отсечение элементов списка по условию. Пока условие истина элементы выкидываются, как только условие ложно все остальные элементы включаются в список:
                              ExpandedWrap disabled
                                dropWhile p xs = fst $ foldl f z xs
                                  where
                                    f (xs, b) x | b && p x = (xs, True)
                                    f (xs, _) x = (xs ++ [x], False)
                                    z = ([], True)
                                 
                                dropWhile (>3) [4,1,2,3,4,5] // [1,2,3,4,5]

                              p - предикат, xs - список
                              Надо преложить на JS. Думаем! :hang:
                              Хотя пока думаю один я :D
                              Сообщение отредактировано: Cfon -
                                Решил по аналогии с drop! :D
                                ExpandedWrap disabled
                                  const dropWhile = (p, xs) => (
                                      xs.reduce(({xs, b}, x) =>
                                          (b && p(x)) ? {xs, b:true} : {xs:[...xs, x], b:false},
                                      {xs:[], b:true}).xs
                                  );
                                   
                                  dropWhile(x => x > 3, [4,1,2,3,4,5] // [1,2,3,4,5]

                                немного были затыки с анонимной функцией, а так изи :D

                                Переменную b в JS можно не передавать в акумуляторном объекте, его можно мутировать в замыкании, тут я просто перенес один в один решение в Хаскелл-стиле где нельзя менять значения переменных :blush:

                                Например вот как будет в императивном стиле JS
                                ExpandedWrap disabled
                                  const dropWhile = (p, xs) => {
                                      var b = true; //исходное состояние
                                      return xs.reduce((xs, x) =>
                                          (b && p(x)) ? xs : (b = false, [...xs, x]),
                                                          //  ^^ изменяем состояние
                                      [])
                                  };

                                как видите код в немного сократился, за счет выкидывания b из аккумуляторного объекта и замены его простым массивом.

                                Первые впечатления от Хаскелла в основном положительные :good:
                                Функциональный стиль, строгая типизация и т.д все классно,
                                но если сравнивать с моим кодингом на JS, на Хаскелл сложнее отлаживать хотя он и строго типизирован, но вот мессажи об ошибках, которые возникаю при компиляции, вгоняют меня в ступор, например
                                ExpandedWrap disabled
                                  hof.hs:81:15: error:
                                      * Couldn't match expected type `[a1]'
                                                    with actual type `([a1], Bool)'
                                      * In the first argument of `(++)', namely `xs'
                                        In the expression: xs ++ [x]
                                        In the expression: (xs ++ [x], False)
                                      * Relevant bindings include
                                          x :: a1 (bound at hof.hs:81:10)
                                          xs :: ([a1], Bool) (bound at hof.hs:81:7)
                                          f :: ([a1], Bool) -> a1 -> ([a1], Bool) (bound at hof.hs:80:5)

                                :wacko:

                                да на JS было много ошибок в рантайме, но хз я их изи правил и находил, чего не скажу пока про Хаскелл :wall:
                                думаю если научусь их читать, то ваще будет шоколадно :D

                                Рекомендую ли я Haskell к изучению новичкам в программировании? Скорее нет, чем да :D
                                а вот тем кто уже мастер императивном программинге, то велком в Хаскелл найдете много интересного! И мозоль в мозге первое время будет большая :D
                                Эт я еще монады не трогал и не прогал GUI, БД и тп, знающие прогеры ну те кто круче меня :D пугают меня ими :lool:
                                Сообщение отредактировано: Cfon -
                                  Очередная шифрограмма от Хаскелл :D
                                  ExpandedWrap disabled
                                    words _ [] = []
                                    words p s = w : words p s'
                                        where
                                            (w, s') = f p $ dropWhile p s
                                            f p (x:xs) | (not . p) x = (x:ys, zs) where (ys, zs) = f p xs
                                            f _ xs = ([], xs)

                                  Что она делает? Получает предикат сравнения, строку, и возвращает список слов.. все :blink: так коротко? я кайфую :hang:
                                  ExpandedWrap disabled
                                    words (==' ') "Lorem Ipsum is simply dummy text of the printing and typesetting industry."
                                    // ["Lorem","Ipsum","is","simply","dummy","text","of","the","printing","and","typesetting","industry."]

                                  Задача та же перевести на JS :wacko:

                                  Кстати в Хаскелле отступы имееют значение! Тут аля как их не расставишь, но у меня с этим не было проблем ибо я всегда нормально их ставил :D
                                  но вот те кто не любит отступы будут в га*не :lool:
                                  Вроде в Пайтоне также. Наверно кодеры Хаскелла и Пайтон дружат :D
                                  Сообщение отредактировано: Cfon -
                                    ExpandedWrap disabled
                                      'Lorem Ipsum is simply dummy text of the printing and typesetting industry.'.split(' ')
                                      Цитата Serafim @
                                      ExpandedWrap disabled
                                        'Lorem Ipsum is simply dummy text of the printing and typesetting industry.'.split(' ')

                                      нет надо показать реализацию JS кода что привел на Haskell :D
                                      То что в JS есть свои функции для обработки строк, я естесно в курсе как бы не наслышке, мой здесь интерес реализовать их в функциональном стиле.
                                      Кстати в Хаскелле уже есть готовая функция words, я ее тут немного переклепал для практики :D

                                      Догадываюсь что тут мало Хаскелистов (, а может и нет вапще :D ) и приведеный мной код не понятен многим, поэтому я ща его расшифрую :D

                                      Короче даю построчный разбор кода
                                      ExpandedWrap disabled
                                        words _ [] = [] // 1
                                        words p s = w : words p s' // 2
                                             where
                                                 (w, s') = f p $ dropWhile p s // 3
                                                 f p (x:xs) | (not . p) x = (x:ys, zs) where (ys, zs) = f p xs // 4
                                                 f _ xs = ([], xs) // 5

                                      Немного поясню стиль написания функций на Хаскелл основан на совпадении образцов (patterns matching), т.е. пишутся простые выражения (уравнения), которые потом выборочно вычисляются в зависимости от совпадения.
                                      1 - совпадение срабатывает в случае когда words вызывается на пустом списке, он же является завершающим вызовом рекурсного вызова words
                                      2 - идет рекурсивный вызов words
                                      3 - вспомогательная функция f собственно выполняет всю работу по разделению слов, вызов dropWhile p s откидывает пробелы вначале строки s и предает ее в функцию f
                                      4 - идет рекурсивный вызов f в результате каждого шага рекурсии возвращется пара или говоря в терминах Хаскелля кортеж (ys, zs), далее он намного изменяется, точнее сам то кортеж не меняется, т.к. в Хаскелл нет переменных в классическом понимании, это просто некое имя для значения или выражения, создается новый кортеж (x:ys, zs) с измененым списком ys, если говорить точнее к нему в голову добавляется значение переменной x
                                      5 - завершающий вызов рекурсии
                                      еще проще сложно описать т.к. надо весь язык капать :D
                                      Сообщение отредактировано: Cfon -
                                        Приветствую вот накодил получилась жесть, как по мне что то не то :D
                                        ExpandedWrap disabled
                                          function words(p, s) {
                                              if (s === '') return [];
                                           
                                              function f(p, s) {
                                                  const a = [...s];
                                                  const {c, s1} = { c: a.shift(), s1: a.join('')};
                                            
                                                  if (!p(c)) {
                                                      const {w, s2} = f(p, s1);
                                                      return {w: [c,...w].join(''), s2};
                                                  }
                                                  return {w:[], s2:s1};
                                              };
                                              
                                              const {w, s2} = f(p, dropWhile(p, [...s]).join(''));
                                              return [w, ...words(p, s2)];
                                          }
                                           
                                          const s = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. ";
                                          const ws = words(c => c === ' ', s);
                                          console.log(ws);
                                          // ["Lorem","Ipsum","is","simply","dummy","text","of","the","printing","and","typesetting","industry."]

                                        в коде есть где то баг, если исходная строка не заканчивается пробелом, то все летит лесом :D
                                        ПС. dropWhile взят из прошлых моих творений что в предыдущих постах постах :D
                                        ладно чет устал я если у вас есть желание найти баг, ну или свой пример запостить велком, а я отдыхать! :huh:
                                        Сообщение отредактировано: Cfon -
                                          Баг нашел, дело в строчке где происходит отделение символа от строки, но пока решения не нашел, временно поставил императивный костыль :D
                                          ExpandedWrap disabled
                                            function words(p, s) {
                                                if (s === '') return [];
                                             
                                                function f(p, s) {
                                                    let [c, ...s1] = s; //<--- тут баг
                                                    if (c === undefined) c = ' '; //<-- костыль
                                             
                                                    if (!p(c)) {
                                                        const {w, s2} = f(p, s1);
                                                        return {w: [c, ...w], s2};
                                                    }
                                                    return {w:[], s2: s1};
                                                };
                                                
                                                const {w, s2} = f(p, dropWhile(p, [...s]));
                                                return [w.join(''), ...words(p, s2.join(''))];
                                            }

                                          Попутно подрихтовал код заюзав деструктиризацию массива вместо прямых манипуляций :D
                                          ExpandedWrap disabled
                                            const a = [...s];
                                            const {c, s1} = { c: a.shift(), s1: a.join('')};

                                          на
                                          ExpandedWrap disabled
                                            let [c, ...s1] = s;
                                          Сообщение отредактировано: Cfon -
                                            Цитата Cfon @
                                            нет надо показать реализацию JS кода что привел на Haskell

                                            ExpandedWrap disabled
                                              function *words(sentence, separator) {
                                                  let buffer = '';
                                               
                                                  for (let char of sentence) {
                                                      if (char === separator) {
                                                          yield buffer;
                                                          buffer = '';
                                                          continue;
                                                      }
                                               
                                                      buffer += char;
                                                  }
                                              }


                                            Прикреплённый файлПрикреплённый файл123123.jpg (277,2 Кбайт, скачиваний: 363)
                                            Сообщение отредактировано: Serafim -
                                              Цитата Cfon @
                                              Баг нашел, дело в строчке где происходит отделение символа от строки, но пока решения не нашел, временно поставил императивный костыль :D

                                              Пофиксил
                                              ExpandedWrap disabled
                                                function words(p, s) {
                                                    if (s === '') return [];
                                                 
                                                    function f(p, s) {
                                                        const [c = ' ', ...s1] = s;
                                                            //    ^^ значение по умолчанию
                                                 
                                                        if (!p(c)) {
                                                            const {w, s2} = f(p, s1);
                                                            return {w: [c, ...w], s2};
                                                        }
                                                        return {w:[], s2: s1};
                                                    };
                                                    
                                                    const {w, s2} = f(p, dropWhile(p, [...s]));
                                                    return [w.join(''), ...words(p, s2.join(''))];
                                                }

                                              Вроде более менее приближен к Хаскелл-стилю, надо еще подрихтовать формы :D

                                              Добавлено
                                              Цитата Serafim @
                                              ExpandedWrap disabled
                                                function *words(sentence, separator) {
                                                    let buffer = '';
                                                 
                                                    for (let char of sentence) {
                                                        if (char === separator) {
                                                            yield buffer;
                                                            buffer = '';
                                                            continue;
                                                        }
                                                 
                                                        buffer += char;
                                                    }
                                                }

                                              ну и где тут функциональный подход Хаскелл? :blink:

                                              очередная императивная реализация :D
                                              Сообщение отредактировано: Cfon -
                                                Вот еще немного рихтовки :D
                                                ExpandedWrap disabled
                                                  function words(p, s) {
                                                    if (s === '') return []; // 1
                                                   
                                                    const f = (p, s) => {
                                                      const [x = ' ', ...xs] = s;
                                                      return !p(x)
                                                        ? ({ys, zs} = f(p, xs), {ys: [x,...ys], zs}) // 4
                                                        : {ys:[], zs: xs} // 5
                                                    };
                                                   
                                                    const {ys: w, zs: s1} = f(p, dropWhile(p, [...s])); // 3
                                                    return [w.join(''), ...words(p, s1.join(''))]; // 2
                                                  }

                                                Оригинал на Хаскелле
                                                ExpandedWrap disabled
                                                  words :: (Char -> Bool) -> String -> [String]
                                                  words _ [] = [] // 1
                                                  words p s = w : words p s' // 2
                                                      where
                                                          (w, s') = f p $ dropWhile p s // 3
                                                           f p (x:xs) | (not . p) x = (x:ys, zs) where (ys, zs) = f p xs // 4
                                                           f _ xs = ([], xs) // 5

                                                Почти один в один :D

                                                В ходе исследования кода JS в попытке приблизить его в функциональному стилю Haskell должен отметить операторы запятая и тернарный, а также синтаксис деструктуризации объектов и массивов, и остаточных элементов ES6 :thanks: Без них мало что получилось! :D
                                                А также группе Helloween и ушам Audio Technica! Они хорошо изолировали меня от окружающих! :D
                                                Сообщение отредактировано: Cfon -
                                                  Пардон! Грубая ошибка! Так нельзя >:(
                                                  ExpandedWrap disabled
                                                    function words(p, s) {
                                                      if (s === '') return [];
                                                     
                                                      const f = (p, s) => {
                                                        const [x = ' ', ...xs] = s;
                                                        return !p(x)
                                                          ? ({ys, zs} = f(p, xs), {ys: [x,...ys], zs})
                                                           //  ^^^^^ создаются глобальные переменные!!
                                                          : {ys:[], zs: xs}
                                                      };
                                                     
                                                      const {ys: w, zs: s1} = f(p, dropWhile(p, [...s]));
                                                      return [w.join(''), ...words(p, s1.join(''))];
                                                    }

                                                  Обратно к корректной форме :D
                                                  ExpandedWrap disabled
                                                    function words(p, s) {
                                                        if (s === '') return [];
                                                     
                                                        const f = (p, s) => {
                                                            const [x = ' ', ...xs] = s;
                                                            if (!p(x)) {
                                                                const {ys, zs} = f(p, xs);
                                                                   //   ^^^^  OK, локальные переменные
                                                                return {ys: [x,...ys], zs};
                                                            }
                                                            return {ys:[], zs: xs};
                                                        };
                                                     
                                                        const {ys: w, zs: s1} = f(p, dropWhile(p, [...s]));
                                                        return [w.join(''), ...words(p, s1.join(''))];
                                                    }

                                                  Фан версия! :D
                                                  ExpandedWrap disabled
                                                    function words(p, s) {
                                                        if (s === '') return [];
                                                     
                                                        const f = (p, s) => (() => {
                                                            const [x = ' ', ...xs] = s;
                                                            return !p(x)
                                                                ? (() => {const {ys, zs} = f(p, xs);return {ys: [x,...ys], zs}})()
                                                                : {ys:[], zs: xs}
                                                        })();
                                                     
                                                        const {ys: w, zs: s1} = f(p, dropWhile(p, [...s]));
                                                        return [w.join(''), ...words(p, s1.join(''))];
                                                    }
                                                  Сообщение отредактировано: Cfon -
                                                    Цитата Cfon @
                                                    ну и где тут функциональный подход Хаскелл?

                                                    Он медленный, жрёт кучу оперативы и не читаемый.
                                                      Цитата Serafim @
                                                      Он медленный, жрёт кучу оперативы и не читаемый.

                                                      Вроде как Haskell рекурсии оптимизирует и они не жрут память, читал где то :)
                                                      а не читаемый потому что функциональный стиль требует иного подхода к чтению :D

                                                      ОК очередное задание, переписать на JS код, который парсит строку на слова и возвращает список из числа повторений каждого слова и самого слова :D
                                                      Вот образец
                                                      ExpandedWrap disabled
                                                        *Main> wordNums "hello world hello"
                                                        [(2,"hello"),(1,"world")]

                                                      Код на Хаскелле
                                                      ExpandedWrap disabled
                                                        wordNums :: String -> [(Int, String)]
                                                        wordNums s = [(length ws, head ws) | ws <- group . qsort . words (==' ') $ s]
                                                         
                                                        words :: (Char -> Bool) -> String -> [String]
                                                        words p s = case dropWhile p s of
                                                          "" -> []
                                                          s' -> w : words p s''
                                                            where (w, s'') = split p s'
                                                         
                                                        qsort :: (Ord a) => [a] -> [a]
                                                        qsort [] = []
                                                        qsort (x : xs) =
                                                            qsort [y | y <- xs, y <= x] ++
                                                            [x] ++
                                                            qsort [y | y <- xs, y > x]
                                                         
                                                        group :: (Eq a) => [a] -> [[a]]
                                                        group [] = []
                                                        group (x:xs) = (x:ys): group zs where (ys, zs) = split (/= x) xs
                                                         
                                                        split :: (a -> Bool) -> [a] -> ([a], [a])
                                                        split p (x:xs) | (not . p) x = (x:ys, zs) where (ys, zs) = split p xs
                                                        split _ xs = ([], xs)

                                                      Функции words, qsort уже переписаны на JS в предыдущих постах, я их для наглядности сюда тоже перенес. Осталось group и wordNums. Ну а split я просто вынес из words для повторного применения в group. Она делить список (строку) на две части согласно предику :D

                                                      Пояснения к коду Хаскелл.
                                                      words - получает исходную строку и возвращает список слов
                                                      group - получает список слов и выделяет рядом лежащие совпадающие слова в отдельные списки, ну возвращает его (список списков)
                                                      sort - понятно сортирует :D
                                                      split - уже писал выше
                                                      ВСЕ! да и я тоже буду переводить го кто шустрее :lool:
                                                      Сообщение отредактировано: Cfon -
                                                        Готова! :D
                                                        ExpandedWrap disabled
                                                          function words(p, s) {
                                                              if (s === '') return [];
                                                              const [w, s1] = split(p, dropWhile(p, [...s]));
                                                              return [w.join(''), ...words(p, s1.join(''))];
                                                          }
                                                           
                                                          function group(xs) {
                                                              if (xs.length == 0) return [];
                                                              const [x, ...xs1] = xs;
                                                              const [ys, zs] = split(x1 => x1 !== x, xs1);
                                                              return [[x, ...ys], ...group(zs)];
                                                          }
                                                           
                                                          function split(p, xs) {
                                                              if (xs.length == 0) return [[],[]];
                                                              const [x, ...xs1] = xs;
                                                              if (!p(x)) {
                                                                  const [ys, zs] = split(p, xs1);
                                                                  return [[x, ...ys], zs];
                                                              }
                                                              return [[], xs];
                                                          }
                                                           
                                                          function dropWhile(p, xs) {...} // см выше
                                                          function qsort(xs) {...} // см quicksort
                                                           
                                                          const wordNums = s =>
                                                              group( qsort( words(c => c == ' ', s))).map(ws => ([ws.length, ws[0]]));
                                                           
                                                          const s = 'hello world hello';
                                                          console.log(wordNums(s));
                                                          // [ [ 2, 'hello' ], [ 1, 'world' ] ]

                                                        Получилось почти в функциональном стиле, почему почти? :D
                                                        1 - в функциях больше одного return
                                                        2 - наличие присваиваний
                                                        Все это вносит некий императизм :D
                                                        Но несмотря на это в обшем код смотрится функционально! :blush:
                                                        Особенно функция wordNums изящно не правда ли? :wizard:
                                                        Сообщение отредактировано: Cfon -
                                                          Цитата Cfon @
                                                          Вроде как Haskell рекурсии оптимизирует и они не жрут память, читал где то

                                                          А зачем оптимизировать что-то, если можно просто вернуть корутину?

                                                          Добавлено
                                                          Цитата Cfon @
                                                          Но несмотря на это в обшем код смотрится функционально!

                                                          Код смотрится отвратно. Я могу сократить его в 10 раз и сделать на порядки читаемее... Хотя, постой, кажется, я уже это делал :whistle:
                                                            Цитата Serafim @
                                                            Код смотрится отвратно. Я могу сократить его в 10 раз и сделать на порядки читаемее... Хотя, постой, кажется, я уже это делал :whistle:

                                                            Го жду :D
                                                                Цитата Serafim @

                                                                И все?! нет батенька от меня так просто не отделаться :lool:
                                                                будьте добры всю функцию wordNums :D

                                                                В прошлом примере я не юзал композицию, в отличие от примера на Хаскелле, давайте заюзим в wordNums композицию и дополнительно для words каррирование. Я не стал юзать кастомную функцию compose и править ручками words, а заюзал библу Ramda
                                                                ExpandedWrap disabled
                                                                  const R = require('ramda');
                                                                   
                                                                  const wordNums = s =>    
                                                                      R.compose(
                                                                          a => a.map(ws => [ws.length, ws[0]]),
                                                                          group,
                                                                          qsort,
                                                                          R.curry(words)(c => c === ' ')
                                                                      )(s);
                                                                   
                                                                  .........

                                                                получилось длинее, но так для практики пойдет :D

                                                                Еще улучшим код, добавим функцию isSpace
                                                                ExpandedWrap disabled
                                                                  const wordNums = s =>    
                                                                      R.compose(
                                                                          a => a.map(ws => [ws.length, ws[0]]),
                                                                          group,
                                                                          qsort,
                                                                          R.curry(words)(isSpace)
                                                                      )(s);
                                                                   
                                                                  const isSpace = c => /[\s\.;,!?-]/.test(c);

                                                                теперь можно изи добавлять символы игнора :D
                                                                Сообщение отредактировано: Cfon -
                                                                  Цитата Serafim @
                                                                  Код смотрится отвратно. Я могу сократить его в 10 раз и сделать на порядки читаемее...

                                                                  И тишина... походу парнишка сдулся? :-?
                                                                  Симка балабол! :D
                                                                  Сообщение отредактировано: Cfon -
                                                                    ExpandedWrap disabled
                                                                      function wordNums(it) {
                                                                          return it.length;
                                                                      }


                                                                    Добавлено
                                                                    А, не, так не получится

                                                                    Добавлено
                                                                    Потому что слова могут быть разделены чем угодно, получается от итератора не получить длины. Т.к. деление по пробелам - некорректно. В итоге:
                                                                    ExpandedWrap disabled
                                                                      return sentence.split(/\W+/).length;


                                                                    Т.е. в функции выше (самой первой) сплит по пробелу надо заменить на сплит по регулярке, а затем длину от итератора.

                                                                    А т.к. JS дерьмо и в нём нет корутин, то вместо return передаём значение в анонимочку

                                                                    Добавлено
                                                                    на пыхе это было бы так:
                                                                    Скрытый текст
                                                                    ExpandedWrap disabled
                                                                      function words(string $sentence): iterable
                                                                      {
                                                                          $buffer = '';
                                                                       
                                                                          foreach (\str_split($sentence) as $char) { // Итератор по чарам
                                                                              if (\preg_match(yield $separator, $char)) { // Корутина разделения символов по регулярке с произвольным разделителем
                                                                                  $buffer = '' && yield $buffer; // Возвращаем буфер
                                                                                  continue;
                                                                              }
                                                                       
                                                                              $buffer .= $char; // Конкатенируем с буфером
                                                                          }
                                                                      }
                                                                       
                                                                      function word_nums(iterable $words): iterable
                                                                      {
                                                                          foreach ($words as $i => $word) { // Пробегаемся по словам
                                                                              yield $word; // Возвращаем слово
                                                                          }
                                                                       
                                                                          return $i; // Возвращаем последний индекс
                                                                      }


                                                                    Добавлено
                                                                    Цитата Cfon @
                                                                    И тишина... походу парнишка сдулся?

                                                                    Да потому что ты хренью страдаешь. Из нормального кода делаешь хрень. Функциональщина нужна там, где она будет профитна, а не везде её пихать. Функции от коллекций в JS работают сразу над всем массивом. Ты его весь держишь в памяти. Это полная дичь. В моём же примере память выделяется ровно в пару-тройку байт. Как только очередное слово находится - память вычищается сразу же.

                                                                    И опять же приходим к тому, что в JS нет вообще ленивых коллекций: https://github.com/ramda/ramda/blob/master/source/map.js#L45

                                                                    А намного правильнее было бы:
                                                                    ExpandedWrap disabled
                                                                      export default *function(cb, iterator) {
                                                                          for (let item of iterator) {
                                                                              yield cb(item);
                                                                          }
                                                                      }
                                                                      Цитата Serafim @
                                                                      Да потому что ты хренью страдаешь. Из нормального кода делаешь хрень. Функциональщина нужна там, где она будет профитна, а не везде её пихать. Функции от коллекций в JS работают сразу над всем массивом. Ты его весь держишь в памяти. Это полная дичь. В моём же примере память выделяется ровно в пару-тройку байт. Как только очередное слово находится - память вычищается сразу же.

                                                                      В каком примере?! :wall:
                                                                      Ты пока написал пол того что делает мой код! Напиши всю wordNums так чтобы не жрало память, хоть на пыхе хоть на чем мля но тока напиши! А не язычком моли :whistle:
                                                                      Код на пыхе что делает? Вывод в итоге какой? Мне надо получить из предложения, список пар где будет слово и число его повторений в предолжении, например
                                                                      "hello world hello" -> [[2, "hello"], [1, " world"]]

                                                                      Да и напиши свой гавнокод как обещал в 10 раз меньше моего гавнокода :D
                                                                      Я буду считать строки :D

                                                                      Добавлено
                                                                      Цитата Serafim @
                                                                      А т.к. JS дерьмо и в нём нет корутин, то вместо return передаём значение в анонимочку

                                                                      почему нет корутин? есть :D
                                                                      генераторы введенные в ES6 поддерживают их :D
                                                                      Сообщение отредактировано: Cfon -
                                                                        Цитата Cfon @
                                                                        Ты пока написал пол того что делает мой код! Напиши всю wordNums так чтобы не жрало память, хоть на пыхе хоть на чем мля но тока напиши!

                                                                        Ну сам попросил:
                                                                        ExpandedWrap disabled
                                                                          foreach ($words as $word) {
                                                                              yield \substr_count($sentence, $word) => $word;
                                                                          }


                                                                        Итератор, который возвращает в качестве ключа количество слов, а в качестве значения само слово.

                                                                        Цитата Cfon @
                                                                        генераторы введенные в ES6 поддерживают их

                                                                        генераторы - это не корутины. У генераторов в ES6 нет возможностей корутин.
                                                                          Цитата Serafim @
                                                                          ExpandedWrap disabled
                                                                            foreach ($words as $word) {
                                                                                yield \substr_count($sentence, $word) => $word;
                                                                            }

                                                                          Итератор, который возвращает в качестве ключа количество слов, а в качестве значения само слово.

                                                                          Вывод какой будет тут? Как можно проверить? И у тебя юзаеться готовая фунция substr_count! ты за кого меня держишь? :D, у меня же все ручками! Ну кроме map :D
                                                                          Я тоже могу привести в одну функцию
                                                                          ExpandedWrap disabled
                                                                            const wordNums = s =>
                                                                                group( qsort( words(c => c === ' ', s))).map(ws => [ws.length, ws[0]]);

                                                                          Если на входе строка к примеру "hello world hello", а на выходе массив, в котором каждый элемент представлял два значения, первое - слово, второе - число его повторов или наоборот без разницы :D. Я уже выше приводил :wall:
                                                                          ExpandedWrap disabled
                                                                            // [ [2, "hello"], [1, "world"] ]

                                                                          У тебя так? :D

                                                                          Цитата Serafim @
                                                                          генераторы - это не корутины. У генераторов в ES6 нет возможностей корутин.

                                                                          Что ты понимаешь под корутинами?
                                                                          Сообщение отредактировано: Cfon -
                                                                            Цитата Cfon @
                                                                            Что ты понимаешь под корутинами?

                                                                            что тут опять начинается?!! было же всё тихо и спокойно... Сифон сам себе байки рассказывал, никого не трогал... и тут вдруг какой-то коротин :oops:

                                                                            Добавлено
                                                                            я фапще не в теме, поэтому буду ляпать для начала, что не попада
                                                                            ExpandedWrap disabled
                                                                              array_count_values( preg_split( '/\s+/', $string ) );
                                                                              Цитата K313 @
                                                                              я фапще не в теме, поэтому буду ляпать для начала, что не попада
                                                                              ExpandedWrap disabled
                                                                                array_count_values( preg_split( '/\s+/', $string ) );

                                                                              да попада :D но тока ты юзаешь готовые функции, а надо ручками :D
                                                                                Цитата Cfon @
                                                                                Я не стал юзать кастомную функцию compose и править ручками words, а заюзал библу Ramda
                                                                                а ты сам то чё? целую либу заюзал?
                                                                                  Цитата K313 @
                                                                                  Цитата Cfon @
                                                                                  Я не стал юзать кастомную функцию compose и править ручками words, а заюзал библу Ramda
                                                                                  а ты сам то чё? целую либу заюзал?

                                                                                  Ramda.compose не относиться к решению нашей задаче, ее можно не юзать.
                                                                                  Вот без compose
                                                                                  ExpandedWrap disabled
                                                                                    const wordNums = s => group( qsort( words(c => c === ' ', s))).map(ws => [ws.length, ws[0]]);



                                                                                  А вот вам императивный вариант wordNums, писал на дровнях :D
                                                                                  ExpandedWrap disabled
                                                                                    function wordNums(s) {
                                                                                        const ws = words(c => c === ' ', s);
                                                                                        const result = [];
                                                                                        const o = {};
                                                                                        
                                                                                        for (const w of ws) {
                                                                                            o[w] = o[w] ? o[w] + 1 : 1;
                                                                                        }
                                                                                        for (const w in o) {
                                                                                            result.push([o[w], w]);
                                                                                        }
                                                                                        return result;
                                                                                    }

                                                                                  Все приходится делать самому! :D

                                                                                  ПС. надо ишо words на императивные рельсы поставить :D
                                                                                  Сообщение отредактировано: Cfon -
                                                                                    ОК а вот и императивный words :D
                                                                                    ExpandedWrap disabled
                                                                                      function words(p, s) {
                                                                                        const result = [];
                                                                                        let word = '', cc;
                                                                                        let i = 0,  len = s.length;
                                                                                        while (i < len) {
                                                                                          cc = s[i];
                                                                                          if (!p(c)) word += cc;
                                                                                          if (p(c) && word !== '') {
                                                                                            result.push(word);
                                                                                            word = '';
                                                                                          }
                                                                                          if (i === len - 1) {
                                                                                            result.push(word);
                                                                                          }
                                                                                        }
                                                                                      }

                                                                                    ПС.  писал на дровнях сильно не пинайте, это чисто императивный стиль :D
                                                                                    Вспомнил старый добрый Си :whistle:
                                                                                    Сообщение отредактировано: Cfon -
                                                                                      Цитата Serafim @
                                                                                      Он медленный, жрёт кучу оперативы и не читаемый.

                                                                                      Зато в свое время в нем были эпичные баги: https://twitter.com/bos31337/status/116372971509121025 :D
                                                                                        Надеюсь теперь с компилятором GHC все порядке :D
                                                                                          Хаскель изучил :D
                                                                                          догадайтесь че я щас изучаю? :D
                                                                                            VBScript?
                                                                                              Цитата nash @
                                                                                              VBScript?

                                                                                              :bad:

                                                                                              Добавлено
                                                                                              Ещё идеи? :D
                                                                                                Ок даю подсказки :D
                                                                                                • C
                                                                                                • Go
                                                                                                • Swift
                                                                                                • Rust
                                                                                                • Python
                                                                                                • Java
                                                                                                • Scala
                                                                                                • Kotlin
                                                                                                • C#
                                                                                                  VBScript?
                                                                                                    Прид*рок не балуйся! :lool:
                                                                                                      Хм... Я думаю это всё же VBScript
                                                                                                        очередная подсказка :D
                                                                                                        8ой язык в списке Форбс :lool:
                                                                                                          VBScript же!
                                                                                                            中文
                                                                                                              Цитата Cfon @
                                                                                                              8ой язык в списке Форбс

                                                                                                              Хм ... там только VBScript! :-?
                                                                                                                я тоже думаю, VBScript. ну а что еще.
                                                                                                                  Ясно, вопрос снят! Не скажу ответ мучайтесь :D
                                                                                                                    А что мучаться-то. Ответ и так очевиден.
                                                                                                                    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                                                                    0 пользователей:


                                                                                                                    Рейтинг@Mail.ru
                                                                                                                    [ Script execution time: 0,1441 ]   [ 17 queries used ]   [ Generated: 16.04.24, 09:59 GMT ]