Как сделать такую функцию SUM(1)(2)(3)... на JS?
HTML-код
- Опубликовано: 9 сен 2024
- #soer #itubeteam
Основной канал для общения и публикации новых видео - Телегарм - t.me/softwaree...
Спонсорство - donate.s0er.ru
Сайт платным контентом - soer.pro
Зеркало для видео Дзен Видео - zen.yandex.ru/...
GitHub - github.com/soe...
Чат для программистов - / discord
Группа ВК - codeart...
Таймкоды:
00:00 Введение
00:50 Простой вариант решения
03:45 Решение с помощью TDD
05:06 Первый тест
09:17 Рефакторинг
11:33 Деструктивные тесты
15:51 Объявления по архитектурным стримам
Исходники - www.patreon.com/posts/41736979
Описание:
Напишите функцию, которая принимает строку из скобок и определяет, допустим ли порядок этих скобок. Он должен возвращать истину, если строка действительна, и ложь, если она недействительна.
Все входные строки будут непустыми и будут состоять только из круглых скобок, скобок и фигурных скобок: () [] {}.
Примеры
"(){}[]" => True
"([{}])" => True
"(}" => False
"[(])" => False
"[({})](]" => False
Всё было превосходно до момента как решение мусора ограничилось лишь первым вызовом... а что если мусор будет дальше? разве должно быть обнуление? а так и будет:
sum(1)(2)()(4);
// 1
// 3
// 0
// 4
Имхо, необходимо и n обрабатывать, и в случае с кратким написанием функции возврат должен быть таким
return (n) => sum(a + (parseInt(n) || 0));
// 1
// 3
// 3
// 7
Могу быть не прав в правильности решения, не js-ник...
По поводу vim:
замена символа (индекс в тесте) - r
Переход до конца блока - %. Таким образом, например, можно быстро вырезать блок: встаёшь на строчку с блоком, v, end, %, d
Двигать курсор вперед до символа - t , назад - T .
А можно сделать так чтобы в итоге возвращалось значение? Например const a=func(1)(2)(3)
Нет тут рекусии, потому что как миниму рекурся должна иметь условие выходи из нее, а тут просто ф-ция возврощает другую ф-цию
В определении рекурсии нет требования иметь условия выхода из неё. Хз чего автор лайкнул коммент.
То, что изначальной функции не происходит именно вызов самой себя, а лишь возврат функции, другое дело
@@kyrylo_alekseev согласен, бесконечная рекурсия - то же рекурсия по определению.
@@d1namis Так тут же простое замыкание...
Тоже смотрел перезалив той видяхи того парня?)
Смотрел оригинал
на самом деле хорошую задачу нашли в альфе)
Евгений, здорово было бы немного усложнить задачу.
Я бы предложил ребятам немного заморочиться и придумать реализацию, которая способна принимать в одном вызове несколько параметров, например:
sum(1,3,0)(4,1,1) // 10
На собеседованиях также нередко просят реализовать возможность возврата итогового значения суммы и его переиспользования:
sum(1)(2)(3) + sum(1)(2) // 9
*Спойлер* для тех, кто заинтересовался: для первого задания нужно рассматривать входные аргументы как массив и аккумулировать числа в этом массиве с помощью метода reduce. Для второго нужно понимать принципы приведения объектов к примитивам. Копайте в сторону Symbol.toPrimitive или valueOf.
let sum = function () {
const result = [...arguments].reduce((a, b) => a + b, (this && this.result) || 0);
console.warn(result);
return sum.bind({result});
}
@@maxr8212 в строгом режиме этот вариант, к сожалению, работать не будет. вызов sum(1) упадёт с ошибкой, так как контекст первого вызова функции sum не привязан к какому-либо объекту. В строгом режиме ссылка this внутри такой функции будет равен undefined. Попытка получить result у undefined и приводит в конечном счёте к ошибке исполнения.
@@Boortwint обновил
let sum = function (a) {
a = [...arguments].reduce((a,b) => a + b)
let closureFunc = function(b) {
b = [...arguments].reduce((a,b) => a + b)
return b ? sum(a + b) : a;
}
closureFunc.toString = () => a;
return closureFunc;
}
import { curry } from "ramda"
Я у мамы инженер.
Но функция Выводит суммы, но не возвращает сумму...
Тоже не понимаю, что за фигня...
@@DEN-tg1yp В задании сказано выводить в консоль, что функция и делает
Можно в таком случае возвращаемой функции добавить метод [Symbol.toPrimitive] который вернет result
В предложенном варианте функции нет рекурсии потому, что там возвращается функция, а не запускается. То есть запускается функция, которая возвращает функцию, которая при вызове запустит первую функцию, но добавив к её аргументу новое значение. То есть функция сама себя не вызывает, а значит рекурсии нет.
Как не вызывается, если возвращается результат выполнения функции sum?)
@@vladick4272 не уловил связку тезиса и аргумента. Поясните. Логично, что при вызове функции sum мы получаем результат выполнения функции sum, но это никак не связано с рекурсией, так все функции работают. Я Вас или не понял, или же Вы чего-то не досказали.
Nikolay Matveychuk , я имею ввиду, что в данном случае, родительская функция sum все таки вызывает саму себя через стрелочную функцию, передавая новое значение. А если так, то это все таки рекурсия
@@vladick4272 она сама себя не вызывает. Она возвращает функцию, при вызове которой вызовется сама. Если описать это более математически, то работает это приблизительно так:
определим множество функций sumₖ(x) = sumₖ₊ₓ
будем считать, что sum(x) = sum₀(x), ну то есть введём удобный псевдоним для sum₀
Вот так и работает предложенная программа, после чего sum(a)(b)(c)(d) просто вызывает последовательно некий набор функций sumₖ
Функция sumₖ(x) сама себя не вызывает, она возвращает другую функцию подобную себе. А то, что в программе это похоже на рекурсию, так это лишь потому, что мы не определяем функции sumₖ заранее (ну нецелесообразно объявлять заранее бесконечное множество функций xD ), а делаем это в теле вызываемой функции по мере необходимости.
Надеюсь смог объяснить суть. То есть вызвать функцию и вернуть функцию - это не одно и то же.
можно порешать классику функции каррирования, мемоизации, композиции :) к стати решение этой задачи заняло около 5 минут функциональным способом, действительно крассивая функция :)
S0ER, большое спасибо за видео! Пример задачи: Есть RESTful API, куда можно отправлять HTTP GET запрос раз в 500 ms. Есть очередь из 100 подобных запросов. Нужно собрать статистику по удавшимся и неудавшимся запросам.
Мне думая, что тут итеративный процесс. Вычисления идут на каждом шаге. А не ждут до конца и только потом вычисляются.
На последних собесах просил соискателей написать функцию каррирования двух аргументов и применить для суммы. Даже после намеков и прямых подсказок большинство хлопает ресницами и спрашивает - а это что за синтаксис, такое вообще возможно? Только один с не особо большим опытом справился и все подробно рассказал, красава.
я на собесах такие вопросы наоборот стараюсь или не задавать или переформулировать. т.к. если человек не знает что такое каррирование - это легко поправимо. а вот если ему рассказать (неважно про каррирование или какой-то алгоритм), а он реализовать не сможет - это уже реально проблема.
@@TwilightSun32 Дело не в конкретном вопросе на знание терминов. Если он не знает, что это, то далее обычно объясняешь сам и смотришь, как человек на это реагирует, как думает, что пытается сделать и т.п. Возможно вместе решаете задачу. Так как цель не завалить, а найти хорошего спеца, то суть не в точном ответе. Просто большинство даже о ФП не слышали и никогда не использую, но пишут, что мега-специалисты в реакте.
@@pavel-orlov если объяснять и смотреть именно на попытки решения конкретной объясненной задаче, то да, это имеет смысл. правда тут вместо каррирования можно брать что угодно другое, что для реализации требует того же уровня знания тех же аспектов языка, на кодварс например хватает задачек типа функция возвращает функцию и т.п.
к слову, на мой взгляд, джаваскрипт вообще располагает к странному пониманию основ программирования в том числе и функциональных штук, да : )
типа вот пиши такую штуку оно же удобно так все пишут и работает... а как работает - это сложности уже, не надо знать... стрёмно.
задача с собеседования
Написать функцию, где решалась бы следующая задача. Найти n-ю цифру последовательности из квадратов целых чисел: 149162536496481100121144...
Например, 2-я цифра равна 4, 7-я 5, 12-я 6. Использовать операции со строками в этой задаче запрещается.
Тоже сталкивался, только на олимпиаде)
Чувствуется мне, что решением будет что-то около "переворота" числа, когда мы каждое число делим на 10, записываем результат и так далее до последней цифры в числе.
Ну что тут такого? Создаешь count
Цикл for
Если в цикле выполняется условие что корень arr[i] это целое число, тогда count ++
Когда count = искомому n, возвращаешь arr[i].
Либо применить filter(), и в отфильтровпнном массиве обратиться к индексу [n]
Первая запись менее красива, но выполнится быстрее
@@mikhail-khoroshev нужно найти цифру, а не все число
10:55
Второй вопрос вроде как предполагает, что ответ на первый вопрос - да :)
И интуитивный, первый приходящий в голову ответ - да, есть.
Но меня напрягает отсутствие явного терминального условия выхода из рекурсии
Здравствуйте) как по вашему мнению, научные степени типа докторских всяких они же на оклад особо сильно не влияют? На них скорее сертификаты повлияют, нежели вузовские степени?
В ИТ? Разве что в какой нибудь гос компании, а в нормальной продуктовой компании на сертификаты/степени и прочее - похрен
Разработка через тестирование довольно часто используется в промышленности хорошими разработчиками
Да, я тоже знаю.
Здесь нет рекурсии, здесь каррирование
Недавно только закончил книгу "composing software" от Эллиота
и как? бустанул скиллы?
@@vladkolesnik2274 сложно сказать. Я читал ее два раза. В первый раз много инфы я пропустил (не стал использовать на практике), а многое не понял. Недавно перечитывал, в этот раз лучше, теперь пытаюсь пользоваться принципами с книги. Книга вообще расчитана не на "бустануть скиллы", а показать другой взгляд на решения задач, которые ты уже решал
@@user-yd7db3wd7w понял, тоже скачал попробую как-нибудь,спасибо за ответ
Как сделать подписку на видео про архитектуру и получить возможность смотреть скрытые стримы?
a=a||0; супер. буду менять typeof und...
как небольшое дополнение
let sum = function (a) {
let closureFunc = b => b ? sum(a + b) : a;
closureFunc.toString = () => a;
return closureFunc;
}
learn.javascript.ru/task/sum-many-brackets
Не знаю будет ли такой вариант быстрее, тут не будет замыканий, но будет проведение типов, что с другой стороны так же ограничивает функцию и она просто будет сбрасыватся в 0 если передать ей что-то неадекватное. ;)
function sum(val) {
const res = (Number.isNaN(+this) ? 0 : +this) + val;
console.log(res);
return sum.bind(res);
}
P.s. рекурсии нет, только биндинг замыканий.
Неплохо работаешь в vim!
В реальной работе - морока такая эти тесты писать.
Поэтому многие их не пишут. Или пишут тяп-ляп. Потому что проверь то, проверь это. Еще и деструктивные проверки.
Но тесты писать - полезно и правильно. Чтоб Боинги потом не падали из-за ошибки в программе.
Кто умеет - пишет, кто не умеет пишет тесты и примеры для поступления на работу. Потом эти великолепные сециалисты знающие все, сыплющие терминами, хорошим английским произношением, и тд. Да вот беда- , нифига не могут программать.
@@dmitriypolynin7273 От части Вы правы. Раньше сильно учили думать, предвидеть в процессе написания. Но все не предусмотреть, максимум 7 сущностей в голове держим в моменте, а где то отвлекут, где то и сам под настроение косяки провтыкаешь, убежишь далеко и вообще забудешь.
Сегодня попалась эта задача на codewars.com, только в вашем случае упрощённый вариант условия у задачи. На codewars условие такое напишите функция add(1)(2)(3) разное кол-во вызовов, которая при сравнении с числом будет возвращать true например add(1) == 1 true. add(1)(2) == 3 true и т.д
да, тоже решал её там, вспомнил.
как по мне это конечно немного разные задачи: в кодварс упор на джсные извращения (нюансы работы ==) добавляется
а тут вон на видео tdd на первом месте (хотя я не в курсе подразумевается ли столь фундаментальный подход на собеседовании)
О каррирование =)
неа
@@DjLeonSKennedy как "неа"?
Видео супер. Обидно, что перешел на JS. Но не важно. Вот зада:
Есть массив целых случайно сгенерированных чисел. Нужно вывести в порядке убывания последовательные цепочки чисел. ожидаемый результат:
999, 998,997, 996
1,2,3
666, 667
0
.... and so on.
Array.from({length: 40}, () => Math.floor(Math.random() * 1000)).sort((a,b) => a - b).reverse()
@@maxr8212 какой смысл делать сортировку и переворачивать, если можно сразу нормально отсортировать?
Агонь
есть задача по реакту приложение, сделать игру, я могу скинуть готовую верстку и сборку, нужно будет добавить код на реакт, такое подойдет? Кстати сегодняшняя задача действительно очень популярна, спасибо за видео. Я на Вас подписан один из первых)
Мой ленивый вариант решения этой задачи)
function sum(num, acc=0) {
console.log(num + acc);
return val => sum(val, num + acc);
}
Как стать патроном? Где написано?
Так трудно описание под видео посмотреть?
Ждём стрим
А можно сделать что бы выводилось только последний раз?
Пикни есди узнаешь ответ.
@@fpv_am Ок. Костылем точно можно, через другую функцию или глобальную переменную, но как именно в одной функции пока не знаю.
Я на собесе переопределил метод toString() для этого. Не перезвонили)
@@yobalomtik Переопределять базовые методы это бич JSа)
более краткий вариант
let sum = function (num) {
const result = (this.result || 0) + num
console.warn(result);
return sum.bind({result});
}
Видео не смотрел, сорри, некогда. Первое, что пришло в голову, если нужно именно вернуть сумму, а не вывод процесса в console.log:
function sum(a, acc) {
if (a === undefined) return acc;
return (b) => {
return sum(b, a+(acc||0));
}
}
sum(1)();
// 1
sum(1)(2)(3)(4)();
// 10
sum(1)?
@@nadirbeknazaraly5136 sum(1)()
Предлагаю загадку: есть двухмерный массив, где 1 - часть реки, 0 - земля, нужно написать функцию которая выведет суммы длин всех рек: 7, 3, 2
[ [1, 0, 0, 1, 0], [1, 1, 0, 1, 1], [0, 1, 1, 0, 0], [1, 0, 1, 1, 0], [1, 0, 0, 0, 0] yadi.sk/i/pE_91KDtTjhlJg
Первый вариант функции sum более производительный, т.к. он не создает каждый раз новую функцию. Но второй вариант sum может ветвиться. Если это ветвление не нужно, то приоритет конечно остается за производительностью, поэтому я бы выбрал первую функцию.
если приоритет за производительностью, то нужно выбирать другой ЯП
@@Dmytro-Tsymbaliuk это не зависит от языка программирования, на любом языке первый вариант будет быстрее.
И JS компилируется довольно производительный машинный код. Я не думаю, что найдется какой-то функциональный язык, который скомпилирует второй вариант программы значительно лучше JS.
@@Mike-hp3fh так надо компилировать человеческий код, плюсы будут намного быстрее
Я ее не правильно понял, я решил что она должна возвращать объект который имеет функцию tostring() чтобы если результат в консоль выводишь он бы автоматически в строку числа переводился. Мне не ответили.
Всё правильно думал. Этот объект с функцией toString - есть твоя возвращаемая функция. В JS всё есть объект. Собственно, тебе только оставалось переопределить метод toString возвращаемой функции, чтобы он возвращал результат суммирования.
В Firefox даже если переопределить методы toString или valueOf, при простом выводе именно в консоль будет выводиться сам объект, например. Одна из причин, отчего этот способ ущербный и подходит только для ответа на интервью.
@@Boortwint формулировка, что "В JS всё есть объект." некорректная
@@kyrylo_alekseev
в консоль выводиться будет не сам объект, а его строковое представление.
"этот способ ущербный и подходит только для ответа на интервью."
Этот способ по сути и был реализован для ответа на интервью. Так как он, по твоим же словам, подходит для этих целей, то не такой он уж и ущербный.
P.S. Говоря о объектной природе JS, я не брал во внимание 7 примитивов. Они не объекты. Это верно.
@@Boortwint "в консоль выводиться будет не сам объект, а его строковое представление."
Или не будет, если это Firefox. Как я и написал уже
Каррирование?
Задача многоконального доступа. Кода есть один ресурс и много независимых потребиттелей каторым рандомно нужен этот ресурс. Как сделать что бы они все вместе не юзали один ресурс
mutex
У меня есть уникальная задача из реального собеседования если инетересно могу поделиться?!
У меня одного горит жопа от "old_console" ? underscore в JS втф....????
camel case рулит, но как-то само собой получилось )
@@S0ERDEVS ничего не имею против underscore, но стандарт есть стандарт )Так то, видео норм
Вроде всё правильно. А Вы говорите о себе. Каждого посетителя интересует он сам. И нет контакта. Жаль, не интересно.
Остановился на 3:35. Но пока немного офигиваю, дорогая редакция. Напишите функцию, которая выдаёт 1 3 6... бла-бла-бла вот функция, запускаем и результат:
1 1 3 6...
Тадам! Стопэ, это же неправильно по условию? Или я чего-то не понимаю? :)))))
Ладно смотрю дальше.
Там 2 вызова было.
@@justkrybik Серьёзно? А чо не 3? :)))
Да не я так. С пьяных глаз. Извиняюсь.
@@justkrybik Да-да, согласен. Там же сначала sum(1) было. Извиняюсь, туплю и невнимаетелен. :)
С мобилы - мелкий текст.
Клаву иногда громче диктора слышно.
первый лайк)
первый лайк)
Объясните, пожалуйста, мне глупому - А в чём вообще смысл городить эту жуткую химеру из цепочки вызовов функции, когда все значения можно передать простым массивом, с которым проще работать?
Я сколько не думаю, всё не могу придумать хоть какое-то практическое применение для подобного, где бы подобная цепочка пригодилась.
Это просто популярный вопрос на знание определённых вещей
Извините если бы мне такое дали на собесе я бы послал их нахрен и не кого бы из знакомых не пускал в эту компанию. Такое дерьмо если они пишут у себя то им не программист нужен а уборщик дерьма
типа очень простая?
@@fellainthewagon7166 типа заморочество и не имеет смысла, это код просто потому что, который сложно читать, а всё что сложно читать это плохой код и значит его нужно переписать. А такие вещи как тут вообще не должны существовать в продакшене, и еще, то что джс так может не значит что это хорошо
Если бы на проде это гавно увидел, то попросил бы чтобы переделал.
Работаю фулстеком, до того как не начал мелльком смотреть мок собеседования и не знал что так можно.
Ну типо и что?) откуда столько фанатизма вокруг синтаксиса?
У меня иногда такое ощущение, что самый говённый код рождается от людей, которые таких задачек гору нарешали.
Это почти декоратор=)))!!!Функция возвращает функцию😎😎😎!!!А он не даёт функциянальному коду умирать!!!
function f(){
let count=0;
console.log(count++);
}
f();//1
f();//1
=)))
0
0