-
Notifications
You must be signed in to change notification settings - Fork 27
closures
warden13 08:54 function makeAdder(x) { function add(y){ return x + y; } return add; }var plusOne = makeAdder(1);console.log(plusOne(1));Мне здесь непонятно, почему аргумент в plusOne передается внутрь как y для add rabinzon 08:56 у тебя makeAdder принимает аргумент x и возвращает другую функцию add - plusOne которая принимает y (edited) warden13 08:59 Спасибо, вроде догоняю point212 08:59 жесть какая. 09:00 как так то? там же вообще по идее y не откуда взяться. azmesmparser 09:00 plusOne просто новое имя для add warden13 09:00 Вот я тоже над этим думал долго)) point212 09:00 А если я просто вызову console.log(plusOne(1)); fatwebdev 09:00 в plusOne лежит
const add = y => 1 + y;
rabinzon
09:02 add = (x,y) => { return x + y } что вернет add? (edited)
point212
09:03 саму функцию наверное
fatwebdev
09:03 Оо
rabinzon
09:03 add(5,5)
warden13
09:03 сумму аргументов
rabinzon
09:03 ?
warden13
09:03 10 вернет
rabinzon
09:04 const sum = add(5,5) где sum = 10
point212
09:04 Неправильно вопрос понял.
rabinzon
09:04 точно так же вместо чисел можно вернуть функцию из функции
point212
09:04 Ну это я понимаю 🙂 Допустим вернули.
kirill.mokevnin
09:05 вопрос на засыпку, а как вызывать эту функцию const sum = x => y => x + y чтобы она вычислила x + y ?
point212
09:05 Ей получается опять подставятся аргументы, которые были переданы изначальной функции?
kirill.mokevnin
09:05 щас проверим ваше понимание
point212
09:05 я и так не понимал 🙂 теперь вообще перестану
warden13
09:05 sum(1,2) ???
kirill.mokevnin
09:05 там же видно что аргумент у sum один
pustato
09:06 sum(1)(2)?
kirill.mokevnin
09:06 бинго (edited)
warden13
09:07 C каждым сообщением все больше понимания)
point212
09:07 С каждым сообщением всё меньше понимания (
rabinzon
09:08 function sum(x) { return function inner(y) {x +y} }
мы из sum вернем другую функцию inner которая готова принять аргумент
warden13
09:08 Еще вопрос на счет объявления функций
В чем преимущество
const someFunc = x => {}
от
09:09 var someFunc = funtion(x) {}
kirill.mokevnin
09:09 чтобы не вдаваться в детали, которые вас сейчас запутают, мы в курсах даем именно такое определение потому что оно очень хорошо показывает (и намекает) на то что функции это тоже данные
point212
09:09 А откуда она возьмёт аргумент? Опять из тех аргументов, которые были переданы изначальной функции? и вызовется вместо неё? Или это произойдёт лишь при втором вызове?
kirill.mokevnin
09:09 и между данными и функциями нет разницы по большому счету (в языках где есть разница это особенность реализации, в математике нет разницы) (edited)
09:10 этого достаточно на текущем уровне, остальное уже связано с особенностями работы вокруг this
09:10 не забивайте голову
09:10 лучше разберите тот пример до конца
warden13
09:10 в closure?
kirill.mokevnin
09:10 там и замыкания и функции как данные
09:11 const sum = x => y => x + y09:11 вот этот пример который в себе содержит все о чем вы говорите 09:11 его понимание даст вам полное понимание происходящего point212 09:11 @rabinzon: пойдёмте в директ. чтобы остальным не мешать :slightly_smiling_face: может у вас получится мне обяснить :slightly_smiling_face: потому что мне кажется, я начинаю догонять rabinzon 09:11 function sum(x) { return function inner(y) {x +y} } var fn = sum(4); @point212: чему равно fn ? kirill.mokevnin 09:11 ребят это тут и надо обсуждать (edited) if22 09:11 прохожу Профессия: PHP-программист / PHP: Построение абстракций. понял что застрял...мозг противиться новым знаниям и умениям. Прошу совета. Есть ли смысл "отложить" этот курс и пока пройти что-нибудь другое? kirill.mokevnin 09:11 хекслет для этого создавался 09:12 и general самый тот канал где нужно разбирать непонимание фундаментальных вещей (edited) point212 09:12 ну просто тут у всех вопросы... параллельно несколько обсуждений вести неудобно же kirill.mokevnin 09:12 все ваши вопросы сводятся к той функции которую я выше описал 09:12 давйате все вместе разберем 09:12 сэкономим всем время point212 09:12 Ну я честно говоря не понял даже синтаксиса. Что за => kirill.mokevnin 09:12 мне гораздо проще/удобнее сразу всем рассказать, чем потом каждому в отдельных чатах point212 09:12 типа объявление функции в js? kirill.mokevnin 09:12 да rabinzon 09:13 @point212: я написал через function) kirill.mokevnin 09:13 простейшая функция в js которая называется identity: const identity = x => x 09:13 идентичность, возвращает переданный аргумент (edited) arbatskiy 09:13 получется эта функция y => x + y, будет теперь таскать за собой x, как туз в рукаве, и в лбом месте ее использовать, где эту функцию решат вызвать kirill.mokevnin 09:13 теперь дальше
const sum = x => y => x + y
09:13 вы можете тут расставить скобки?
09:14 скиньте сюда этот же пример, но так чтобы тело функции было обернуто в скобки
09:14 ()
09:14 не важно может ли этого синтаксис js или нет, мы щас для концептуального понимания
warden13
09:14 const sum = x => ( y => x + y ) ?
kirill.mokevnin
09:14 воооот
09:15 сколько принимает аргументов sum и что возвращает?
warden13
09:15 1 аргумент и возвращает функцию
kirill.mokevnin
09:15 @warden13: я вижу что вы понимаете, давайте другим дадим)
warden13
09:15 Окей)
kirill.mokevnin
09:16 @point212: напиши плс определение функции, которую мы получим вызвав функцию выше вот так sum(5)
09:16 и назови ее const plusFive
09:16 то есть вот эту запись const plusFive = sum(5) надо развернуть в определение функции
arbatskiy
09:16 а как правильно сформулировать тут, что x замкнуто для функции? или функция замкнута для x?
kirill.mokevnin
09:16 эквивалентное
warden13
09:17 получается в plusFive будет хранится функция y => 5 + y ?
kirill.mokevnin
09:17 @if22: да, пройди курсы js по порядку, там гораздо мягче мы даем эти знания, они сами войдут в мозг) (edited)
09:18 @warden13: да, но надо чтобы это другие осознали
if22
09:18 @kirill.mokevnin: спасибо! оно вроде бы всё понятно, а как практику делать начинаешь так...
warden13
09:19 И толк от многих видеообъяснений, когда есть слак)
point212
09:19 @kirill.mokevnin: извините, работа навалилась 😞 вот только освободился
kirill.mokevnin
09:21 ок, пока вы изучаете пример выше
09:21 даю более сложный
09:21
const sum = x => { const inner = y => { return x + y; };
x = 10; return inner; }
console.log(sum(1)(5))
point212 09:21 const sum = x => (y => (x + y)) вот так вот, нет? kirill.mokevnin 09:21 что будет введено на экран? 09:21 @point212: да, абсолютно верно (edited) arbatskiy 09:22 интересный пример! не буду говорить предположения, подожду других 🙂 warden13 09:23 6 arbatskiy 09:23 по идее Inner должна тащить за собой свое окружение, в том числе x = 10, я так думаю point212 09:24 Т.е. когда для вот этой функции const sum = x => y => x + y вызвается sum(1)(5) - первый раз вызывается внешняя функция, и ей передается 1, а потом уже ка результат ее вызывается внутренняя, и ей передается 5. Типа (sum(1))(5). Я правильно понял? kirill.mokevnin 09:24 правильно, но тут тонкий семантический момент, после вызова первой функции, вам наружу возвращается внутренняя 09:24 поэтому она вызывается не внутри первой, а снаружи, после вызова первой 09:24 вот этот момент понятен? 09:25 по сути вы внутри определяете новую функцию const f = ... и ниже делаете return f; 09:25 поэтому можно было бы написать const plusOne = sum(1) 09:25 вот эта функция вернулась point212 09:25 Да. Теперь понятен. kirill.mokevnin 09:25 и дальше где угодно plusOne(10) 09:25 на выходе 11 09:26 как видите функции это данные 09:26 их можно и возвращать из функций и передавать в другие функции point212 09:26 А если опять plusOne(10)? Оно опять по кругу пойдёт? Или это уже будет только лишь вернувшаяся функция работать? kirill.mokevnin 09:26 а вот выше вопрос был, напишите определение этой функции 09:26 plusOne 09:26 сюда 09:26 тогда вы сразу все поймете point212 09:27 Да. Это я и раньше понимал. 🙂 Но применял очень ограниченно. kirill.mokevnin 09:27 ну так напишите) 09:27 ждемс point212 09:27 Сейчас прочитаю и осмыслю и напишу kirill.mokevnin 09:27 кстати сущности языка обладающие такими свойствами называются объектами первого рода (класса), слово объект тут используется в общем смысле "какая-то хрень" point212 09:27 Это же мы уже про более сложный пример, который const sum = x => { const inner = y => { return x + y; }; x = 10; return inner; }console.log(sum(1)(5)) kirill.mokevnin 09:27 не 09:27 это про plusOne 09:28 А если опять plusOne(10)? Оно опять по кругу пойдёт? Или это уже будет только лишь вернувшаяся функция работать? вот этот вопрос говорит что вы не до конца понимаете что теперь из себя представляет функция plusOne point212 09:29 Да просто мы тут уже написали кучу разных кусков кода. И который из них plusOne я запутался. kirill.mokevnin 09:29 const plusOne = sum(1) 09:29 const sum = x => y => x + y 09:29 нужно написать определение функции plusOne эквивалентное тому что написано выше 09:30 чтобы было понятно, что в ее теле 09:30 и пойдет ли оно по кругу point212 09:30 Маленький вопросик, т.к. я JS не знаю. const это просто объявление переменной или реально константа? kirill.mokevnin 09:30 константа да 09:30 вам не нужен новый синтаксис чтобы это написать 09:30 все есть тут 09:31 const plusOne = ... warden13 09:31 Я писал 6, но потом понял что когда выполняется return inner, функция за параметр х возмет 10, т.к. он встретиться первым при поиске того самого параметра, следовательно sum(1)(5) вернет 15, а не 6. Она просто не дойдет до х=1 kirill.mokevnin что будет введено на экран? Posted in #generalToday at 09:21 kirill.mokevnin 09:31 что будет вместо троеточия 09:31 @warden13: ответ правильный, но размышления которые к нему привели - нет (edited) 09:32 это называется позднее связывание (то самое которое алан кей называет главной фичей ооп) warden13 09:32 Позднее связываение - это тот же hoisting? kirill.mokevnin 09:33 @point212: сейчас ответственный момент для того чтобы в голове сработало "эврика" и все встало на свои места 09:33 нет 09:33 hoisting это особенность реализации движка js 09:33 очень специфичная штука 09:33 хотя вру, hoisting в спецификации описан 09:33 изначально так просто движок сделали 09:33 потом стандартизировали 09:33 щас убежусь на всякий) point212 09:34 у меня в голове сработала защита пока что. Хочется зажмуриться и сделать ресет мозгу 09:34 Секунду. Сейчас опять от работы отобьюсь чтобы не мешали думать kirill.mokevnin 09:34 давайте, просто вот это тот барьер который надо сломать 09:34 иначе все время стенка будет 09:35 так вот про позднее связывание и пример выше 09:36 js работает по, так называемой, модели окружениями (edited) 09:36 окружение это область памяти в которой записываются key value пары 09:36 это очень важно, еще раз повторю окружение это область памяти 09:36 хм, чот жирный не сработал) 09:36 когда вы пишите const x = 5; 09:37 то где то в кишках js создается ассоциативный массив в который это дело записывается 09:38 но чтобы про эту модель дальше говорить, нужно проговорить другую модель, которая гораздо более простая и разбирается в первых двух главах сикп 09:38 это подстановочная модель вычислений 09:40 это крайне простая вещь, главное что в ней происходит это бета редукция 09:40 то есть когда у вас есть функция const sum x => y => x + y, то она по сути заменяет имена на их значения 09:41 это возможно только в случае неизменяемости 09:41 если x = 5, то это не присваивание (в такой модели), это логическое выражение 09:41 как в математике "допустим x это 5" 09:41 и оно не может поменяться 09:42 и это дает вам возможность все последующие вхождения x заменить на 5 09:42 и ваша программа (на самом деле теорема) остается корректной (edited) 09:42 вы всегда можете представлять вычисление программы как последовательность бета редукций (подстановок) 09:43 до тех пор пока у вас выражение не развернется в плоское арифметическое 5 + 3 * 7 - 9 09:43 которое уже редуцируется до конкретного числа 09:43 что не понятно? 😄 09:43 краткое изложение сикпа за 5 минут point212 09:43 Вот как раз последние 3 строчки весьма понятно. kirill.mokevnin 09:44 @point212: а от вас я жду определение функции) point212 09:44 Это как в математике x + ( x + y + ( x - y)) kirill.mokevnin 09:44 это и есть математика 😉 point212 09:44 никакх проблем с передчей внутрь скобок Х нету. 09:44 Да. Но будучи записанной согласно синтаксису она теряет наглядность kirill.mokevnin 09:44 это уже ваши тараканы point212 09:44 Я толкьо вернулся к компу ) Сейчас перечитаю и напишу kirill.mokevnin 09:44 функциональные языки так и устроены (семантически) 09:44 по факту конечно все работает гораздо сложнее, но снаружи поведение именно такое 09:45 поэтому можно его именно так и моделировать point212 09:45 да. это я тоже видел. просто в математике эту простую вещь не называют замыканиями 🙂 kirill.mokevnin 09:45 а вот модель с окружениями на порядок сложнее, она необходима из за изменяемости 09:45 в математике замыкание это совершенно другое да, мы об этом понятии в курсе говорим 09:45 замкнутые множества вот это все 09:46 модель с окружениями требует наличия как раз такой области памяти в которой хранится связь между именем и значением 09:46 из за того что значение может менятся 09:46 поэтому получается что когда вы делаете
const sum = x => { const inner = y => { return x + y; };
x = 10; return inner; }
console.log(sum(1)(5))
09:46 вот эта строчка return x + y; 09:47 еще кое что забыл, окружения бывают двух видов 09:47 1) глобальное 2) локальные azmesmparser 09:47 жирный одна звездочка *test* kirill.mokevnin 09:47 глобальное одно, локальное каждый раз при заходе в функцию организуется 09:47 у каждой функции свое локальное 09:47 и они так выстраиваются в цепочки 09:48 в итоге js (да любой язык с такой моделью) внутри себя содержит дерево из этих окружений 09:48 globalEnv -> local1 -> local2 09:48 это только одна из веток 09:48 будут еще globalEnv -> local22 -> local23 09:48 напомню что каждое окружение это табличка key value 09:48 где key это имя типа const x 09:48 а значение это собственно значение 09:49 так вот как происходит отработка этого кода выше 09:49 return x + y; 09:49 нам нужно подставить x 09:49 js смотрит в текущее окружение (текущий локальный скоп) 09:49 и не видит там x 09:49 говорит текущему скоупу, нука дай мне своего родителя 09:49 и смотрит у него 09:49 там уже находит x 09:49 и говорит скоупу, нука дай текущее значение 09:49 и какое у него текущее значение? warden13 09:49 10 kirill.mokevnin 09:50 вооот 09:50 так оно и рабтает 09:50 просто же?) warden13 09:50 Получается я не совсем неправильно мыслил, он все таки первым натыкается на х=10 и с ним работает, не доходя до параметра х в аргументах 09:50 А так да, очень просто arbatskiy 09:51 о, я какжется догаладся как оно должно быть) kirill.mokevnin 09:51 этой модели миллион лет 09:51 появилась в лиспах задолго до рождения нашего pavel-k 09:51 если бы этот разговор состоялся вчера, то решение логики без логики заняло бы у меня 3 минуты вместо 30 😃 kirill.mokevnin 09:51 которому тридцатка (edited) warden13 09:52 Я заметил edit )))) kirill.mokevnin 09:52 я посчитал не правильно) 09:52 так ну ским появился в 70 09:52 так что минимум 46 лет) 09:52 но я уверен что и до него это было 09:53 в одной из первых версий лиспа маккартни 09:53 это шестидесятые 09:53 @point212: мы ждем определение функции 09:53 я не отстану! 😄 point212 09:54 Пишу в блокнотике рядом. Вроде уже даже написал. 09:54 И откуда у вас только желание с каждым возиться и в голову вбивать. Это ж никаких сил не хватит на всех. kirill.mokevnin 09:55 представьте что мы уже больше года тут этим занимаемся) pavel-k 09:56 говорят, что чем больше объясняешь другим, тем лучше понимаешь сам... kirill.mokevnin 09:57 мы на самом деле создали хекслет чтобы научиться программировать 😄 konstantin6487 09:58 Вроде это и есть самое основное. Как функции вызывают друг друга. На codewars я 3 уровня набрал и дальше тупик. Не то что проблема в непонимании JS, а в непонимании принципа программирования, point212 09:58
Дано:
const sum = x => y => x + y
const plusOne = sum(1)
Ход решения:
разобьём первую функцию на части, чтобы понятнее было.
sum =
x => ( y=>(x + y) )
не понятно. перепишем в привычном виде.
func sum(x){
func inn(y){
ret x+y
}
}
вроде вот так.
Тогда после выполнения
const plusOne = sum(1)
plusOne должно быть
plusOne = func inn(y) { ret 1 + y }
Т.е. пока что ничего не вычислено.
kirill.mokevnin 09:58 @konstantin6487: вы совершенно правы, вот наши курсы как раз этот барьер проламывают 09:59 за это понимание отвечает абстрактное мышление 09:59 все правильно const plusOne = y => 1 + y; (edited) 10:00 вы задавали вопрос: "пойдет ли оно по кругу" 10:00 ответите теперь сами? point212 10:05 Не пойдёт. 10:05 Если вызвыать ещё одни раз, уже const Two = plusOne(2) = 1+ 2; kirill.mokevnin 10:06 ну и теперь должно быть довольно очевидно что мы можем делать любую вложенность: const sum = x => y => z => x + y + z warden13 10:07 const sum = x => { const innerSum = y => { const secondInnerSum = z => { return x + y + z; } return secondInnerSum; } return innerSum; }const plusOne = sum(1); const plusTen = plusOne(9); 10:07 Я это написал 5 минут назад)) kirill.mokevnin 10:08 для закрепления такой пример: const compose = x => y => value => x(y(value)) (edited) arbatskiy 10:08 кстати про юдасити, вот в этом курсе как раз рассказывают про всякие скоупы довольно подробно и с картинками https://classroom.udacity.com/courses/ud015 kirill.mokevnin 10:08 кто может привести пример использования? konstantin6487 10:08 При вызове функции, куда бы её ни передали в коде – она будет искать переменные сначала у себя, а затем во внешних LexicalEnvironment с места своего «рождения». Вы про это? almazsr 10:08 Суперпозиция функций matvey.bogomolov 10:10 Ооо, жаль.. такие разборки пропустил) А кто-нибудь читал статьи про лямбда абстракции по ссылке из задания "Числа Чёрча"? Вот это конечно темка, не для слабонервных) kirill.mokevnin 10:11 console.log(compose(x => x * 5)(x => x - 10)(100)); arbatskiy 10:11 compose(isEven)(plusOne)(2) kirill.mokevnin 10:11 что выдаст этот вызов?) 10:12 я понял что нам надо добавить в квизы на сайт almazsr 10:12 490? arbatskiy 10:12 450? kirill.mokevnin 10:12 ушел обновлять курсы warden13 10:12 450 kirill.mokevnin 10:12 кто еще как думает?) 10:12 @point212: ? point212 10:13 Не понятная запсь эта... это же не вызов функции. Чтобы во что-то развренулось надо вызвать. konstantin6487 10:13 490 matvey.bogomolov 10:13 490 vitalyusov 10:13 450 kirill.mokevnin 10:13 как это не вызов 10:13 name() - это вызов point212 10:13 Я про вот это const compose = x => y => value => x(y(value)) kirill.mokevnin 10:14 правильный ответ 450 warden13 10:14 УРА!))) roman_gemini 10:14 @arbatskiy: false 🙂 almazsr 10:14 Да, 450. Порядок перепутал atosdo 10:14 (100 - 10) * 5 kirill.mokevnin 10:14 хехе konstantin6487 10:15 Я посчитал не правильно,! kirill.mokevnin 10:15 вот когда у вас такие штуки в голове будут на раз два раскладываться, можете считать что произошел левел ап point212 10:15 @kirill.mokevnin: так я правильно понимаю что выражение const compose = x => y => value => x(y(value)) это пока не вызов функции? kirill.mokevnin 10:15 да это определение 10:15 как обычно сначала расставьте скобки вокруг тел функций 10:15 чтобы было видно point212 10:16 И вызвать ее правильно можно только вот так compose(1)(2)(3) 10:16 т.е. если вызовем лишь compose(1) ничего не посчитается, kirill.mokevnin 10:16 да, и вопрос был в том что вернется при таком вызове console.log(compose(x => x * 5)(x => x - 10)(100)); 10:16 compose(1)(2)(3) упадет с ошибкой point212 10:17 Ну я до этого не дошёл ещё. Я --> :slowpoke: 10:17 Почему упадёт с ошибкой? Потому что ожидает что первые два вызова будут функцями в обязательном порядке? vitalyusov 10:18 будет пытаться вызывать 2 и 1 как функции 10:18 а это не функции 10:18 так? warden13 10:18 Вроде да point212 10:18 А как вы делаете так, что у вас кусочки кода расцвечиваются? kirill.mokevnin 10:18 используем маркдаун 10:18 он поддерживается полностью тут point212 10:18 Ясно. Надо будет погуглить warden13 10:19 x(y(value)) - тут уже х и у вызываются как функции vitalyusov 10:19 только объявляются point212 10:20 console.log(compose(x => x * 5)(x => x - 10)(100)) развернется в 450<-((100-10)*5)<-(100-10)<-(100) 10:20 Я так понял? 10:21 @kirill.mokevnin: проверьте пожалуйста ход моих рассуждений. konstantin6487 10:22 очевидно что да matvey.bogomolov 10:22 Вроде да. count 10:22
const madness = ({a}) => ((a) =>(([{a}]) => (a *= 7, (a => ({a: a})))(a))(a))(a); console.log(madness({a: [{a: 6}]}).a);
point212 10:23 Спасибо, ребята ))) kirill.mokevnin 10:23 самое главное что это знание не конкретного языка 10:23 это общая концепция пришедшая к нам из лямбда исчисления 10:24 зная ее, вы на любом языке сможете писать эффективно, где поощрается использование функций высшего порядка point212 10:24 Я до этого думал что понимаю как работают компиляторы/интерпретаторы. И вообще компьютер. Как парсится код. Но таких вещей в моей "детской" практики не встречалось. Вот что значит учиться программированию по настоящему. Как науке. А не тому, чему учат у нас в институтах.... И понятно теперь почему всё седые гуру программирования говорят - учите сначала ЛИСП. konstantin6487 10:25 Вот кстати развернуто про это из собеседования: определите на каком уровне вы? https://habrahabr.ru/post/226325/ Хабрахабр Интересная задачка для интервью, карринг и частичное применение функции Хожу по job interview. Где-то скучно, где-то весело. Где-то интересно. На одном из таких меня попросили написать функцию, которая умеет складывать два числа. Я... point212 10:25 Надо перепройти ту лекцию Руби, где про аккумулятор. Может теперь пойму как оно считается kirill.mokevnin 10:25 лучше пройти курс "основы программирования" 10:25 там очень хорошо разбирается итеративный процесс на рекурсивных функциях point212 10:25 @kirill.mokevnin: вам отдельно спасибо за возню kirill.mokevnin 10:26 главное чтобы хороших программистов становилось все больше matvey.bogomolov 10:26 Вроде немного по другому же там. Там все левоассоциативно вычисляется. Если я правильно понял. Т.е. f1 f2 f3 f4 == (((f1 f2) f3) f4) я про лямбда исчисление и к тому, что есть небольшие отличия, усложняющие восприятие. Тут так, там иначе но основа то да, она одна (edited) kirill.mokevnin 10:26 сходимость равенство гильберово пространство! вступайте в ряды фурье! -)