20:42

Геолог-анархист

я либо убер пьян, либо ультра туп.

 

нифига не понимаю замыкание

 

может мне кто-нибудь это на пальцах объяснить?



Комментарии
16.11.2010 в 20:55

Дык там всё объяснено, если я сам понял, конечно :)
Это функция, которая использует внешнюю переменную - именно внешнюю, а не передаваемую через параметры.
Только это вроде как плохой стиль - понятность и читаемость кода ухудшается.
Или я отстал от жизни ?

Пример практически тот же, что и в вики :
int x = 10;

int func1(int y) // тут есть замыкание
{
return x+y;
}

int func2(int x, int y) // а тут нет :)
{
return x+y;
}
16.11.2010 в 21:04

Геолог-анархист
ч.е. то не понимаю. вот в приведенном примере с замыканием - x у нас выступает как бы как глобальная переменная, но при этом является локальной? т.е. основная фишка в том, что мы её в функцию не передаем, но по контексту компилятор подставляет правильную переменную?

(я вики раза два прочитал. примеры кодов разобрал, но все равно на голове не уложилось, что это и нахрена надо.)
16.11.2010 в 21:11

Про компиляторы лучше не надо, ИМХО - понять не поможет, а действуют они по разному :)

не обязательно глобальная - т.е. не переменная самого верхнего уровня, а просто внешняя - т.е. переменная, которая определена на уровень или несколько уровней выше, и , как следствие, видна в пространстве имен вложенной функции без объявления...

глобальная - это всё таки когда выше уровня нет :)

а функция может быть вложена одна в другую - это не существенно, возможно, в данном случае, но разница есть...

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

только так делать не стоит - не вижу смысла - экономия писанины мизерная, а вернешься к коду через неделю, или не дай бог, через год, и нихрена не поймёшь :)
16.11.2010 в 21:12

опять же ИМХО - ООП рулит :)))
16.11.2010 в 21:17

Геолог-анархист
вот судя по описанию, не все там так просто.

по ходу понять и прочувствовать поможет только написание примеров.

ведь для чего-то это замыкание придумали? не для того ж, чтоб экономить при вызове один аргумент, имея после этого кучу гемороя с поддержкой кода.
16.11.2010 в 21:18

Вообще лучше спросить на каком-то форуме программистов (например, в сообществе www.diary.ru/~programming/ ) - я не программил уже много лет, вдруг ошибаюсь :)
16.11.2010 в 21:19

Геолог-анархист
а ООП это да. хорошо =)
16.11.2010 в 21:20

Может когда-то это и оправдано, с теми же глобальными переменными, когда их много.
16.11.2010 в 21:22

Геолог-анархист
>> Вообще лучше спросить на каком-то форуме программистов
да судя по всему, мой вопрос дюже нубовский. есть подозрение, что регистрироваться, чтобы задать его - лучший способ нарваться на молчание(в лучшем случае) или смехуёчки да пиздахаханьки.
16.11.2010 в 21:25

мне кажется у тебя предвзятое отношение к программерам :)))
Тут вон спрашивают в соседнем сообществе, как устроена девственная плева - и вежливо получают ответы и пожелания удачи :)
Люди становятся добрее, чтоли :)
16.11.2010 в 21:30

Геолог-анархист
с другой стороны - писал тыщу лет без замыканий, ну так и хер с ними.

а вот как устроена девственная плева я, кстати, так и не знаю. сообщество анатомов/антропологов было? ,) или просто вопрос из серии "чо с ней делать?" ? ,)))
16.11.2010 в 21:32

www.diary.ru/~kruzhok/p134307683.htm

Ну тока это.. не обижайте маленьких :)))
16.11.2010 в 21:34

Геолог-анархист
ахаха. чудесно

>>не обижайте маленьких

там народ и так оторвался =)

но в целом оборжали по-доброму так. не зло. даже удивлен.
17.11.2010 в 18:32

Мегакрендель: заколебарь, жаболекарь, зомболекарь, лежебокарь
Да нет, дело не в локальных и глобальных переменных, а в свободных и связанных.

Замыкание растёт из языков вроде лиспа, и уж там используется в хвост и гриву. Приведу примеры на диалекте лиспа, который так и называется, Clojure («зомыканее»).

(defn kuku [x y] (+ x y))

Эта строчка определяет функцию kuku, которая берёт два аргумента x и y и возвращает их сумму (+ x y). Здесь никаких замыканий нет.

(defn kuku1 [x] #(+ x %))

Эта строчка определяет функцию kuku1, которая берёт один аргумент x и возвращает безымянную функцию #(+ x %). Вот эта безымянная функция и есть замыкание. Она берёт один аргумент y (или называй его как хочешь, здесь название переменной можно не указывать) и возвращает (+ x y).

Это как сопряжённые пространства в математике. Например, бра-кет в квантовой механике: можно рассматривать <ψ|φ> как функцию от двух аргументов ψ и φ, а можно как функцию <ψ| от одного аргумента |φ>.

Ну и вообще функцию от эн аргументов всегда можно переписать как функцию одного аргумента, возвращающую функцию от эн минус одного аргумента.
17.11.2010 в 18:56

Заболекарь интересно, а практический пример использования можно, чтобы лучше понять ?
17.11.2010 в 20:03

Геолог-анархист
вот да. хорошо бы пример из жизни. когда замыкание - лучший способ решить задачу.
17.11.2010 в 20:04

Мегакрендель: заколебарь, жаболекарь, зомболекарь, лежебокарь
Ну вот чуть более практический пример — счётчик.

(defn make-counter [] (let [x (atom -1)] #(swap! x inc)))

Вот мы определили функцию make-counter, которая никаких аргументов не берёт, создаёт переменную x, равную минус единице, и возвращает безымянную функцию #(swap! x inc), которая при каждом вызове увеличивает x на один и возвращает. Вот мы даём ей имя:

(def c1 (make-counter))

Вызываем (c1). Она возвращает 0. Вызываем ещё раз. Возвращает 1. Вызываем ещё раз. Возвращает 2. И так далее.

(def c2 (make-counter))

Вызываем (c2), возвращает 0. Ещё раз. 1. Вызываем (+ (c1) (c2)). Возвращает 5. Вызываем ещё раз. Возвращает 7. Ещё раз. 9. И так далее.

А вот так такой же счётчик выглядит на common lisp, тоже через замыкание (из какой-то пдфки на просторах интернета):

(defun make-counter ()
(let ((x -1))
(lambda () (setq x (+ x 1)))))

17.11.2010 в 20:50

Геолог-анархист
вощем почитал доки, вроде маленько в голове уложилось. хотя пока все равно не представляю задач, которые мне может понадобиться решить таким методом.
18.11.2010 в 10:50

баянолог Тю, Михаил, вы што, шутите? Стукнитесь ко мне в асю, я вас закидаю примерами. Для javasсript это в каждой строке.

BlindPew Это, уважаемый, теперь называется не "плохой стиль", а "модное функциональное программирование", ага )))
18.11.2010 в 11:07

Tzota а можно мне тоже ещё модных примеров ? хоть в умыл ?
18.11.2010 в 14:35

Блин, я чото как начал писать, как начал, и уже пару страниц налабал, а все объяснение идет и идет. Кажется, я не то пишу.
Допустим, в разделе "ссылки" в википедийной статье есть чудная статья - habrahabr.ru/blogs/webdev/38642/
Там есть примеры.

Но вопрос-то в другом стоит, если я правильно понимаю. Примеров дохера, вопрос - как ООП-щику понять, зачем нужно замыкание? Ответ - никак. ООП-щику оно не надо. Чтобы замыкание заиграло смыслом, надо чтобы язык этому способствовал. В русском нет артиклей, но есть окончания. В английском - наоборот. Как объяснить русскому, зачем использовать артикли? Пока он говорит по-русски - незачем.

1. Область видимости. У ООПа для этого есть классы и область видимости. В javasсript нет классов. И чтобы спрятать переменную от другого скрипта, я могу разве что в замыкание ее спрятать.

2. Связи между объектами (контекст исполнения). В ООПе все просто - есть кнопка, по кнопке щелкнули, в обработчике есть обращение к this. Что такое this? Правильно, кнопка, объект, у нас же объектно-ориентированный язык. В функциональном языке этим this скорее всего окажется... сама функция-обработчик. Чо делать? Ага, перед определением обработчика написать var context = this;, где this - это кнопка. И в обработчике обращаться к context, сохраненному замыканием.

Вот эти примеры все в википедии - нафига человеку создавать "специализированную функцию из более общей"?

Там пример на Lua замечательный. Функция "плюсователь_на_два".
Зачем такое делать?
Ну был бы у меня ООП, я б двойку передал в конструктор и сохранил в приватной переменной. И при вызове метода к параметру прибавлял бы эту приватную переменную.
А в жабаскрипте у меня нету классов. Нет приватных переменных. Есть замыкание. Вот и извращаюсь как могу, да.

>>хорошо бы пример из жизни. когда замыкание - лучший способ решить задачу.

Замыкание - это, чаще всего, не "лучший способ решить задачу". Чаще - единственно возможный из-за синтаксиса языка. Иногда - более краткий с точки зрения синтаксиса. Но чтобы "лучший" - хм...
18.11.2010 в 15:37

Tzota спасибо
18.11.2010 в 17:44

Геолог-анархист
Tzota вот. спасибо тебе даня, ответил таки на вопрос "нахера козе баян". я ж пытался в голове сложить ООП и замыкания - и таки мозгу нехорошо было.
а вот теперь идеология кристальная ясна.

тебе надо преподавательствовать или учебники писать. =)
18.11.2010 в 18:55

Завсегда пожалуйста! )

Сложить ООП и замыкания можно. Но особой потребности в этом, чаще всего, нет. Да, есть случаи, когда это экономит пол страницы кода. Но чтобы без этого "не жить" - нееее.

Расширенная форма

Редактировать

Подписаться на новые комментарии
Получать уведомления о новых комментариях на E-mail