Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.119.131.178] |
|
Сообщ.
#1
,
|
|
|
Здрасте!
начал изучать Haskell вот пытаюсь перевести на JS код с Haskell но тока в функциональном стиле JS nouns = ["frog","raven","ribbit"] adjectives = ["lazy","angry","tiny","happy","shy"] mixin nouns adjectives = [adj ++ " " ++ noun | adj <– adjectives, noun <– nouns] Выхлоп [ "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, пока стена |
Сообщ.
#2
,
|
|
|
Сам порешал
function mixin(nouns, adjs) { return nouns.reduce((a, noun) => { const v = adjs.map(adj => { return adj + ' ' + noun; }); return [...a, ...v]; }, []); } На хаскелле как то более проще думать такие задачи, лямбда исчисление рулит! Haskell: mixin nouns adjs = [adj ++ " " ++ noun | adj <– adjs, noun <– nouns] Так изменил в более функциональный стиль JS, но все равно не так очевидно как на Хаскеле const mixin = (nouns, adjs) => nouns.reduce((a, noun) => [...a, ...adjs.map(adj => adj + ' ' + noun)], []); |
Сообщ.
#3
,
|
|
|
Продолжаю изучать удивительный Haskell!
Еще одна задачка на поиск прямоугольных треугольников, дано три списка с числами от 1 до 10 например, надо найти все совпадения прямоугольных треугольников. На хаскеле изи! 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] Выхлоп [(4,3,5),(3,4,5),(8,6,10),(6,8,10)] Как теперь это на JS написать? Добавлено Переключил моск с функционального на императивный режим Оказывается тут идет тупой перебор по трем циклам 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; } |
Сообщ.
#4
,
|
|
|
Одно замечание по коду, в Хаскеле все функции автоматически каррируются
на JS это будет выглядеть так // Каррированная версия 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); зачем Хаскель это делает? да хз я еще не дошел до этого... вроде бы это связано с его реализацией, а именно лямбда функциями в данном коде на JS это делать не обязательно |
Сообщ.
#5
,
|
|
|
Разобрался зачем
Для того чтобы юзать их в функциях высшего порядка, например 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 все проще map (triples aa bb) [[1..5],[6..10]] // [[(3,4,5)],[(6,8,10)]] Кто не понял объясняю, каррированная функция передается функции высшего порядка путем частичного применения Добавлено Очередной вопрос, вот на Haskell код так называемой быстрой сортировки quicksort [] = [] quicksort (x : xs) = quicksort [a | a <- xs, a <= x] ++ [x] ++ quicksort [a | a <- xs, a > x] как его переделать на JS |
Сообщ.
#6
,
|
|
|
Вот вам функционально-подобная попытка на JS приблизится к великому Хаскеллу
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 присутствует |
Сообщ.
#7
,
|
|
|
Для евангелистов reduce коим являюсь сам , вот более оптимизированая версия за счет одного цикла, вместо двух в случае с filter:
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])]; } Цикла? Да-да не удивляйтесь! В JS все равно надо переключаться в императивный режим |
Сообщ.
#8
,
|
|
|
Продолжаю переносить задачки из Хаскель на JS
вот исходная задачка на удаление определенного числа элементов из списка с использованием рекусии: drop 0 xs = xs drop _ [] = [] drop n (x:xs) = drop (n-1) xs а вот та же но через foldl (это аналог reduce в JS) drop 0 xs = xs drop _ [] = [] drop n xs = foldl (\xs _ -> tail xs) xs [1..n] С рекурсией на JS не было проблем 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? Небольшая поправочка в Хаскелле все данные иммутабельны, а у меня тут исходный массив array меняется, что не в Хаскел-стиле! Правим: function drop(n, array) { const origin = [...array]; if (n === 0) return origin; if (array.length == 0) return []; origin.shift(); return drop(n-1, origin); } |
Сообщ.
#9
,
|
|
|
ВСЕ ПРОСТО!! я забыл что в JS можно изменять состояние, это ж не Хаскель
Мде сложно переключаться с функционального на императивный режим, надо тернироваться Вот решение, получается еще проще чем в Хаскелле 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 еще проще function drop(n, array) { if (n === 0) return array; if (array.length == 0) return []; return array.filter(() => (n-- <= 0)); } да и начальные условия тут тоже можно опустить function drop(n, array) { return array.filter(() => (n-- <= 0)); } Хотя я погорячился сказав что проще Хаскеля не проще! куда ж еще проще? drop n xs = foldl (\(_:xs) _ -> xs) xs [1..n] Да в JS уже есть функция удаления splice, но моя цель перевести с Haskell на JS в функциональном стиле, хотя в предыдущих вариантах был применен полу императивный стиль, а не фунциональный и решение в Haskell стиле требует еще покумекать ну т.е. сделать без мутации переменной n. |
Сообщ.
#10
,
|
|
|
Так так так... ща рожу... а не показалось
|
Сообщ.
#11
,
|
|
|
.... иииии! родил зверюшку!
function drop(n, array) { const v = [...Array(n)].map((_,n) => n + 1); return v.reduce(xs => { xs.shift(); return xs; }, [...array]); } Объясняю что тут происходит. Я не сразу допедрил как можно это решить без мутации n! Сила императивного стиля моск реально морозит но после долгих насилований себя я прозрел! если внимательно посмотреть на код Хаскелля видно что он просто производит свертку по числовому списку, а не по целевому списку! Вот где фокус то был! Ну а дальше дело техники, генерирую массив чисел от 1 до n поскольку в JS нет встроенного генератора массива как в Хаскелле и далее делаю свертку хотя это на самом деле не свертка, а простая мутация исходного массива путем выкидывания лишних элементов Все тоже можно было сделать тупо в цикле, но мне хотелось приблизить код к Хаскел-стилю, ну те. к функциональному стилю Немного видоизменил код чтобы максимально приблизится к Haskell: const genN = n => [...Array(n).map((_, n) => n + 1)]; const drop = (n, xs) => genN(n).reduce(xs => (xs.shift(), xs), [...xs]); Вроде бы уже похоже на функциональный стиль |
Сообщ.
#12
,
|
|
|
Реализация drop через свертку исходного списка
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 получилось длиннее, но более понятно теперь надо перевести на JS OK. будем думать. ПС. в последнее время я стал адептом краткой нотации |
Сообщ.
#13
,
|
|
|
Готово! Максимально приближенный Хаскель-стиль
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 ); Нравится мне эта шифрограмма! |
Сообщ.
#14
,
|
|
|
Продолжаем, на очереди dropWhile, его суть отсечение элементов списка по условию. Пока условие истина элементы выкидываются, как только условие ложно все остальные элементы включаются в список:
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. Думаем! Хотя пока думаю один я |
Сообщ.
#15
,
|
|
|
Решил по аналогии с drop!
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] немного были затыки с анонимной функцией, а так изи Переменную b в JS можно не передавать в акумуляторном объекте, его можно мутировать в замыкании, тут я просто перенес один в один решение в Хаскелл-стиле где нельзя менять значения переменных Например вот как будет в императивном стиле JS const dropWhile = (p, xs) => { var b = true; //исходное состояние return xs.reduce((xs, x) => (b && p(x)) ? xs : (b = false, [...xs, x]), // ^^ изменяем состояние []) }; как видите код в немного сократился, за счет выкидывания b из аккумуляторного объекта и замены его простым массивом. Первые впечатления от Хаскелла в основном положительные Функциональный стиль, строгая типизация и т.д все классно, но если сравнивать с моим кодингом на JS, на Хаскелл сложнее отлаживать хотя он и строго типизирован, но вот мессажи об ошибках, которые возникаю при компиляции, вгоняют меня в ступор, например 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) да на JS было много ошибок в рантайме, но хз я их изи правил и находил, чего не скажу пока про Хаскелл думаю если научусь их читать, то ваще будет шоколадно Рекомендую ли я Haskell к изучению новичкам в программировании? Скорее нет, чем да а вот тем кто уже мастер императивном программинге, то велком в Хаскелл найдете много интересного! И мозоль в мозге первое время будет большая Эт я еще монады не трогал и не прогал GUI, БД и тп, знающие прогеры ну те кто круче меня пугают меня ими |
Сообщ.
#16
,
|
|
|
Очередная шифрограмма от Хаскелл
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) Что она делает? Получает предикат сравнения, строку, и возвращает список слов.. все так коротко? я кайфую 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 Кстати в Хаскелле отступы имееют значение! Тут аля как их не расставишь, но у меня с этим не было проблем ибо я всегда нормально их ставил но вот те кто не любит отступы будут в га*не Вроде в Пайтоне также. Наверно кодеры Хаскелла и Пайтон дружат |
Сообщ.
#17
,
|
|
|
'Lorem Ipsum is simply dummy text of the printing and typesetting industry.'.split(' ') |
Сообщ.
#18
,
|
|
|
Цитата Serafim @ 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.'.split(' ') нет надо показать реализацию JS кода что привел на Haskell То что в JS есть свои функции для обработки строк, я естесно в курсе как бы не наслышке, мой здесь интерес реализовать их в функциональном стиле. Кстати в Хаскелле уже есть готовая функция words, я ее тут немного переклепал для практики Догадываюсь что тут мало Хаскелистов (, а может и нет вапще ) и приведеный мной код не понятен многим, поэтому я ща его расшифрую Короче даю построчный разбор кода 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 - завершающий вызов рекурсии еще проще сложно описать т.к. надо весь язык капать |
Сообщ.
#19
,
|
|
|
Приветствую вот накодил получилась жесть, как по мне что то не то
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."] в коде есть где то баг, если исходная строка не заканчивается пробелом, то все летит лесом ПС. dropWhile взят из прошлых моих творений что в предыдущих постах постах ладно чет устал я если у вас есть желание найти баг, ну или свой пример запостить велком, а я отдыхать! |
Сообщ.
#20
,
|
|
|
Баг нашел, дело в строчке где происходит отделение символа от строки, но пока решения не нашел, временно поставил императивный костыль
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(''))]; } Попутно подрихтовал код заюзав деструктиризацию массива вместо прямых манипуляций const a = [...s]; const {c, s1} = { c: a.shift(), s1: a.join('')}; на let [c, ...s1] = s; |
Сообщ.
#21
,
|
|
|
Цитата Cfon @ нет надо показать реализацию JS кода что привел на Haskell 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) |
Сообщ.
#22
,
|
|
|
Цитата Cfon @ Баг нашел, дело в строчке где происходит отделение символа от строки, но пока решения не нашел, временно поставил императивный костыль Пофиксил 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(''))]; } Вроде более менее приближен к Хаскелл-стилю, надо еще подрихтовать формы Добавлено Цитата Serafim @ function *words(sentence, separator) { let buffer = ''; for (let char of sentence) { if (char === separator) { yield buffer; buffer = ''; continue; } buffer += char; } } ну и где тут функциональный подход Хаскелл? очередная императивная реализация |
Сообщ.
#23
,
|
|
|
Вот еще немного рихтовки
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 } Оригинал на Хаскелле 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 Почти один в один В ходе исследования кода JS в попытке приблизить его в функциональному стилю Haskell должен отметить операторы запятая и тернарный, а также синтаксис деструктуризации объектов и массивов, и остаточных элементов ES6 Без них мало что получилось! А также группе Helloween и ушам Audio Technica! Они хорошо изолировали меня от окружающих! |
Сообщ.
#24
,
|
|
|
Пардон! Грубая ошибка! Так нельзя
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(''))]; } Обратно к корректной форме 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(''))]; } Фан версия! 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(''))]; } |
Сообщ.
#25
,
|
|
|
Цитата Cfon @ ну и где тут функциональный подход Хаскелл? Он медленный, жрёт кучу оперативы и не читаемый. |
Сообщ.
#26
,
|
|
|
Цитата Serafim @ Он медленный, жрёт кучу оперативы и не читаемый. Вроде как Haskell рекурсии оптимизирует и они не жрут память, читал где то а не читаемый потому что функциональный стиль требует иного подхода к чтению ОК очередное задание, переписать на JS код, который парсит строку на слова и возвращает список из числа повторений каждого слова и самого слова Вот образец *Main> wordNums "hello world hello" [(2,"hello"),(1,"world")] Код на Хаскелле 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. Она делить список (строку) на две части согласно предику Пояснения к коду Хаскелл. words - получает исходную строку и возвращает список слов group - получает список слов и выделяет рядом лежащие совпадающие слова в отдельные списки, ну возвращает его (список списков) sort - понятно сортирует split - уже писал выше ВСЕ! да и я тоже буду переводить го кто шустрее |
Сообщ.
#27
,
|
|
|
Готова!
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' ] ] Получилось почти в функциональном стиле, почему почти? 1 - в функциях больше одного return 2 - наличие присваиваний Все это вносит некий императизм Но несмотря на это в обшем код смотрится функционально! Особенно функция wordNums изящно не правда ли? |
Сообщ.
#28
,
|
|
|
Цитата Cfon @ Вроде как Haskell рекурсии оптимизирует и они не жрут память, читал где то А зачем оптимизировать что-то, если можно просто вернуть корутину? Добавлено Цитата Cfon @ Но несмотря на это в обшем код смотрится функционально! Код смотрится отвратно. Я могу сократить его в 10 раз и сделать на порядки читаемее... Хотя, постой, кажется, я уже это делал |
Сообщ.
#29
,
|
|
|
Цитата Serafim @ Код смотрится отвратно. Я могу сократить его в 10 раз и сделать на порядки читаемее... Хотя, постой, кажется, я уже это делал Го жду |
Сообщ.
#30
,
|
|
|
Сообщ.
#31
,
|
|
|
И все?! нет батенька от меня так просто не отделаться будьте добры всю функцию wordNums В прошлом примере я не юзал композицию, в отличие от примера на Хаскелле, давайте заюзим в wordNums композицию и дополнительно для words каррирование. Я не стал юзать кастомную функцию compose и править ручками words, а заюзал библу Ramda 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); ......... получилось длинее, но так для практики пойдет Еще улучшим код, добавим функцию isSpace 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); теперь можно изи добавлять символы игнора |
Сообщ.
#32
,
|
|
|
Цитата Serafim @ Код смотрится отвратно. Я могу сократить его в 10 раз и сделать на порядки читаемее... И тишина... походу парнишка сдулся? Симка балабол! |
Сообщ.
#33
,
|
|
|
function wordNums(it) { return it.length; } Добавлено А, не, так не получится Добавлено Потому что слова могут быть разделены чем угодно, получается от итератора не получить длины. Т.к. деление по пробелам - некорректно. В итоге: return sentence.split(/\W+/).length; Т.е. в функции выше (самой первой) сплит по пробелу надо заменить на сплит по регулярке, а затем длину от итератора. А т.к. JS дерьмо и в нём нет корутин, то вместо return передаём значение в анонимочку Добавлено на пыхе это было бы так: Скрытый текст 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 А намного правильнее было бы: export default *function(cb, iterator) { for (let item of iterator) { yield cb(item); } } |
Сообщ.
#34
,
|
|
|
Цитата Serafim @ Да потому что ты хренью страдаешь. Из нормального кода делаешь хрень. Функциональщина нужна там, где она будет профитна, а не везде её пихать. Функции от коллекций в JS работают сразу над всем массивом. Ты его весь держишь в памяти. Это полная дичь. В моём же примере память выделяется ровно в пару-тройку байт. Как только очередное слово находится - память вычищается сразу же. В каком примере?! Ты пока написал пол того что делает мой код! Напиши всю wordNums так чтобы не жрало память, хоть на пыхе хоть на чем мля но тока напиши! А не язычком моли Код на пыхе что делает? Вывод в итоге какой? Мне надо получить из предложения, список пар где будет слово и число его повторений в предолжении, например "hello world hello" -> [[2, "hello"], [1, " world"]] Да и напиши свой гавнокод как обещал в 10 раз меньше моего гавнокода Я буду считать строки Добавлено Цитата Serafim @ А т.к. JS дерьмо и в нём нет корутин, то вместо return передаём значение в анонимочку почему нет корутин? есть генераторы введенные в ES6 поддерживают их |
Сообщ.
#35
,
|
|
|
Цитата Cfon @ Ты пока написал пол того что делает мой код! Напиши всю wordNums так чтобы не жрало память, хоть на пыхе хоть на чем мля но тока напиши! Ну сам попросил: foreach ($words as $word) { yield \substr_count($sentence, $word) => $word; } Итератор, который возвращает в качестве ключа количество слов, а в качестве значения само слово. Цитата Cfon @ генераторы введенные в ES6 поддерживают их генераторы - это не корутины. У генераторов в ES6 нет возможностей корутин. |
Сообщ.
#36
,
|
|
|
Цитата Serafim @ foreach ($words as $word) { yield \substr_count($sentence, $word) => $word; } Итератор, который возвращает в качестве ключа количество слов, а в качестве значения само слово. Вывод какой будет тут? Как можно проверить? И у тебя юзаеться готовая фунция substr_count! ты за кого меня держишь? , у меня же все ручками! Ну кроме map Я тоже могу привести в одну функцию const wordNums = s => group( qsort( words(c => c === ' ', s))).map(ws => [ws.length, ws[0]]); Если на входе строка к примеру "hello world hello", а на выходе массив, в котором каждый элемент представлял два значения, первое - слово, второе - число его повторов или наоборот без разницы . Я уже выше приводил // [ [2, "hello"], [1, "world"] ] У тебя так? Цитата Serafim @ генераторы - это не корутины. У генераторов в ES6 нет возможностей корутин. Что ты понимаешь под корутинами? |
Сообщ.
#37
,
|
|
|
Цитата Cfon @ Что ты понимаешь под корутинами? что тут опять начинается?!! было же всё тихо и спокойно... Сифон сам себе байки рассказывал, никого не трогал... и тут вдруг какой-то коротин Добавлено я фапще не в теме, поэтому буду ляпать для начала, что не попада array_count_values( preg_split( '/\s+/', $string ) ); |
Сообщ.
#38
,
|
|
|
Цитата K313 @ я фапще не в теме, поэтому буду ляпать для начала, что не попада array_count_values( preg_split( '/\s+/', $string ) ); да попада но тока ты юзаешь готовые функции, а надо ручками |
Сообщ.
#39
,
|
|
|
Цитата Cfon @ а ты сам то чё? целую либу заюзал? Я не стал юзать кастомную функцию compose и править ручками words, а заюзал библу Ramda |
Сообщ.
#40
,
|
|
|
Цитата K313 @ Цитата Cfon @ а ты сам то чё? целую либу заюзал? Я не стал юзать кастомную функцию compose и править ручками words, а заюзал библу Ramda Ramda.compose не относиться к решению нашей задаче, ее можно не юзать. Вот без compose const wordNums = s => group( qsort( words(c => c === ' ', s))).map(ws => [ws.length, ws[0]]); А вот вам императивный вариант wordNums, писал на дровнях 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; } Все приходится делать самому! ПС. надо ишо words на императивные рельсы поставить |
Сообщ.
#41
,
|
|
|
ОК а вот и императивный words
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); } } } ПС. писал на дровнях сильно не пинайте, это чисто императивный стиль Вспомнил старый добрый Си |
Сообщ.
#42
,
|
|
|
Цитата Serafim @ Он медленный, жрёт кучу оперативы и не читаемый. Зато в свое время в нем были эпичные баги: https://twitter.com/bos31337/status/116372971509121025 |
Сообщ.
#43
,
|
|
|
Надеюсь теперь с компилятором GHC все порядке
|
Сообщ.
#44
,
|
|
|
Хаскель изучил
догадайтесь че я щас изучаю? |
Сообщ.
#45
,
|
|
|
VBScript?
|
Сообщ.
#46
,
|
|
|
Цитата nash @ VBScript? Добавлено Ещё идеи? |
Сообщ.
#47
,
|
|
|
Ок даю подсказки
|
Сообщ.
#48
,
|
|
|
VBScript?
|
Сообщ.
#49
,
|
|
|
Прид*рок не балуйся!
|
Сообщ.
#50
,
|
|
|
Хм... Я думаю это всё же VBScript
|
Сообщ.
#51
,
|
|
|
очередная подсказка
8ой язык в списке Форбс |
Сообщ.
#52
,
|
|
|
VBScript же!
|
Сообщ.
#53
,
|
|
|
中文
|
Сообщ.
#54
,
|
|
|
Цитата Cfon @ 8ой язык в списке Форбс Хм ... там только VBScript! |
Сообщ.
#55
,
|
|
|
я тоже думаю, VBScript. ну а что еще.
|
Сообщ.
#56
,
|
|
|
Ясно, вопрос снят! Не скажу ответ мучайтесь
|
Сообщ.
#57
,
|
|
|
А что мучаться-то. Ответ и так очевиден.
|