LINUX.ORG.RU

Не понимаю, что такое замыкание (closure)

 ,


5

6

Если почитать SICP, то замыкания - это такое свойство функции, что, например, «мы говорим, что операция объединения данных обладает замыканием в том случае, если результаты объединения этой операции могут объединяться этой же операцией». Поэтому я думал, что суть примера с языком описания изображений в том, что это круто, когда наши процедуры обладают этим свойством - из несложных операций с изображениями мы можем получать сложные, потому что операция над изображением - это изображение.

Но если прочитать вики, то «Замыкание (англ. closure) в программировании — функция, в теле которой присутствуют ссылки на переменные, объявленные вне тела этой функции и не в качестве её параметров (а в окружающем коде).» Ну и что? Получается просто, что процедура использует глобальные переменные, ничего примечательного тут вроде и нет.

Так что такое замыкание? Помогите разобраться.

Ответ на: комментарий от drBatty

Спасибо, кэп. Я в курсе про регистры. Как отдельное извращение для отдельной программы они вполне годятся, но полноценное ПП на регистрах не построить - их слишком мало. И полноценный язык для ПП должен работать со стеком - иначе ему контекст будет негде сохранять.
Не надо путать конкретные процедуры, написанные для конкретной задачи - и общий подход. Общий подход ПП требует стека - ибо у процедуры есть свой собственный внутренний контекст. Можно, конечно, теоретически говорить о ПП без собственных контекстов, при наличии только глобальных данных - но мне неизвестны примеры таких ЯП, даже из ранних. А Вам?

svu ★★★★★
()
Ответ на: комментарий от yyk

Абсолютно не трудно. Дело ж не в поддержке на уровне аппаратуры - а в самой концепции. До Тюринга, как я понял, ее просто не было.

svu ★★★★★
()
Ответ на: комментарий от svu

Хм... Вот есть гарантия, что до Тьюринга ни кто не использовал (не издавая при этом книжки) подобный подход? Нет её.

yyk ★★★★★
()
Ответ на: комментарий от svu

т.е. до того, как кто-то умный не «вывел» понятия (определения) «бег» и «ходьба», люди не ходили и не бегали?

yyk ★★★★★
()
Ответ на: комментарий от svu

Общий подход ПП требует стека - ибо у процедуры есть свой собственный внутренний контекст.

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

anonymous
()
Ответ на: комментарий от svu

Можно, конечно, теоретически говорить о ПП без собственных контекстов, при наличии только глобальных данных - но мне неизвестны примеры таких ЯП, даже из ранних. А Вам?

Ассемблер x86.

anonymous
()
Ответ на: комментарий от svu

Тьюринг только дал _формальное описание_ уже давным-давно де-факто существующему понятию.

anonymous
()
Ответ на: комментарий от anonymous

Ассемблер x86.

Думаю все же svu интересуют примеры языков, появившихся до Фортрана, не?

korvin_ ★★★★★
()
Ответ на: комментарий от anonymous

Если нет формального понятия и осознания явления - невозможно создавать ничего на его основе. Включая ЯП.

svu ★★★★★
()
Ответ на: комментарий от svu

Не надо путать конкретные процедуры, написанные для конкретной задачи - и общий подход. Общий подход ПП требует стека - ибо у процедуры есть свой собственный внутренний контекст.

вот как раз контекст в ПП и не важен. Потому и стек тоже не нужен(в общем случае). Я же говорю: «процедурой» может вполне быть стопка перфокарт.

Можно, конечно, теоретически говорить о ПП без собственных контекстов, при наличии только глобальных данных - но мне неизвестны примеры таких ЯП, даже из ранних. А Вам?

любой ассемблер. Нет там никаких контекстов в общем случае. Ну и соответственно любой древний процедурный ЯП, например C, в котором контексты на самом деле — синтаксический сахар. При желании, любой контекст в сишечке ломается магией указателей.

drBatty ★★
()
Ответ на: комментарий от svu

Для использования в ЯП, технология должна пройти через минимальный уровень рефлексии.

не должна. Вам же сказали, что бегать и ходить можно просто так, без всякой рефлексии. Вторичное использование кода — это вполне здравая идея, и для её реализации не нужно никакое обоснование. Стек тоже появился сам по себе, без всяких математических исследований.

drBatty ★★
()
Ответ на: комментарий от svu

Покажите мне процедурный ЯП до фортрана. Где бы было понятие (в языке) процедуры.

процедуре не обязательно быть «понятием». Стопка перфокарт — просто стопка перфокарт. Вот Васе лень было считать синус, и он взял у Пети стопку перфокарт, которая считает синус. Перед этим он пробил одну перфокарту, которая прибавляет к аргументу PI/2, и потом вставил петину стопку. Получилась стопка, которая вычисляет косинус.

drBatty ★★
()
Ответ на: комментарий от svu

Если нет формального понятия и осознания явления - невозможно создавать ничего на его основе. Включая ЯП.

кто вам сказал, что не было формального понятия и осознания явления процедуры у Бэббиджа?

drBatty ★★
()
Ответ на: комментарий от svu

А при чем тут call/return? Оно для процедур совершенно излишне.

anonymous
()
Ответ на: комментарий от svu

Но все совершенно спокойно создавали. Тьюринг дал описание абстрактной машины, которое имело плюс тот, что отличалось простотой. Но любая реализация корректно работающего тьюринг-полного вычислителя (или хотя бы полный проект такого вычислителя) сама являлась де-факто формально строгой спецификацией вычислителя, т.к. полностью и однозначно задавала его семантику. И этого вполне достаточно чтобы писать ЯП.

anonymous
()
Ответ на: комментарий от drBatty

Ну отдельного понятия он не вводил, однако идею декомпозиции, понятное дело, была, т.к. это совершенно естественно, ну как дышать.

anonymous
()
Ответ на: комментарий от anonymous

Но любая реализация корректно работающего тьюринг-полного вычислителя (или хотя бы полный проект такого вычислителя) сама являлась де-факто формально строгой спецификацией вычислителя, т.к. полностью и однозначно задавала его семантику.

++

И этого вполне достаточно чтобы писать ЯП.

а ЯП уже написан. Это язык данного вычислителя.

ЗЫЖ на самом деле IRL Тьюринг полный вычислитель невозможен, ибо IRL невозможно сделать бесконечность. Потому «полнота» ограниченная во всех _реальных_ ЯП, ну за исключением brainfuck'а разве-что. В сишечке например размер указателя задан, и равен константе. Хоть в стандарте и не определена эта константа, но то, что это константа(известная во время компиляции) — определено. Потому даже сишечка не является Тьюринг-полной в строгом смысле.

drBatty ★★
()
Ответ на: комментарий от anonymous

Ну отдельного понятия он не вводил, однако идею декомпозиции, понятное дело, была, т.к. это совершенно естественно, ну как дышать.

ну потому и не выводил :-)

drBatty ★★
()

тред не читай(тока 1 заметил про омонимы) своими словами отвечай.

1. операция (в матане) замкнута если её результат от аргументов в том же множестве , что и аргументы.

например + чисел натуральных от нуля и дальше - замкнуто.

а вот - натуральных нет ( так мы расширяем до целых)

теперь на целых вычитание замкнуто.

таким же образом умножение на целых замкнуто

а деление на целых нет.

а вот деление на рациональных без нулю замкнуто ибо (a/b)/(c/d)==(a*d)/(b*c)

таким же образом действительные числа не замкнуты на операции извлечения корня ( из отрицательных получается чисто мнимое) - а вот комплексные замкнуты отностительно извлечения корня.

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

- в языках где есть сборка мусора замыкания достаточно удобны.

отличие от вложенных процедур/функций в том что в обычных алгол-языках(паскаль тот же) записи активации были в порядке FILO поэтому достаточно стека , в замыканиях же получается «дерево» вместо линии .

qulinxao ★★☆
()
Ответ на: комментарий от drBatty

ээээ в классическом C замыкания ваяют путём явного дополнительного аргумента - указателя на структуру ( короче эдакий самопальных this) - закат солнца в ручную.

qulinxao ★★☆
()
Ответ на: комментарий от drBatty

ну блин кури историю как в второй половине 50ых эволюционировал IPL ( и откуда в алголе логический IF ( из лиспа ))

qulinxao ★★☆
()

1. операция (в матане) замкнута если её результат от аргументов в том же множестве , что и аргументы.

мы вроде не про матан.

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

угу. ИМХО замыкание — такой объект, который содержит функцию(в т.ч. её локальные переменные) + какие-то ещё переменные (нелокальные).

В сишечке все функции образуют замыкание со всеми глобальными переменными (исключая не экспортируемые переменные из других модулей)

ИМХО передача ссылки/указателя тоже является замыканием, причём так оно потому, что пространство указателей в сишечке является глобальным, т.е. указатель указывает на объект независимо от того, в каком контексте находится данный указатель. По этой причине сделать в сишечке сборщик мусора(который работает с простыми «глупыми» указателями) невозможно(хотя и возможно, если указатели «умные» (smart pointers), они потому и называются «умными», ибо учитывают контекст)

drBatty ★★
()
Ответ на: комментарий от qulinxao

ээээ в классическом C замыкания ваяют путём явного дополнительного аргумента - указателя на структуру ( короче эдакий самопальных this) - закат солнца в ручную.

ага. И что тут странного? См. выше, для замыканий нужны разные контексты, а по дефолту в сишечке всего один общий контекст. Т.е. замыкания есть(передача по ссылке/указателю), но толку от них немного(разве что несколько байт/тактов экономишь).

drBatty ★★
()
Ответ на: комментарий от qulinxao

ну блин кури историю как в второй половине 50ых эволюционировал IPL ( и откуда в алголе логический IF ( из лиспа ))

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

drBatty ★★
()
Ответ на: комментарий от drBatty

Вам же сказали, что бегать и ходить можно просто так, без всякой рефлексии.

Аналогии такие аналогии. Мы говорим о достаточно конкретном технологическом понятии - ПП. Технология не существует до того, как ее придумали и осознали (и назвали). Даже если какие-то ее элементы использовали раньше.

svu ★★★★★
()
Ответ на: комментарий от drBatty

Возвращаю вопрос: а кто сказал, что было?

svu ★★★★★
()
Ответ на: комментарий от drBatty

процедуре не обязательно быть «понятием».

Чтобы ЯП назывался процедурным ЯП - обязательно. Язык без понятия процедуры не может быть процедурным. Язык без понятия объекта не может быть ОО.

svu ★★★★★
()
Ответ на: комментарий от drBatty

porkrind.org/missives/closures-in-straight-c/

с мусорщиков всё таки удобней.

а вот чё не пойму почему в обероне замыканий в явном виде(т.е функции не первого класса, а какие-то нелегалы-иммигранты ) нет - при живом то мусорщике.

qulinxao ★★☆
()
Ответ на: комментарий от svu

Чтобы ЯП назывался процедурным ЯП - обязательно. Язык без понятия процедуры не может быть процедурным. Язык без понятия объекта не может быть ОО.

Да нет же, нужно не понятие, а соответствующее выразительное средство. Если язык позволяет выделить кусок кода и потом его выполнять в произвольном месте - то значит процедуры есть, и не важно, как будет _называться_ это средство в данном конкретном ЯП. Главное, чем оно является по определению.

anonymous
()
Ответ на: комментарий от anonymous

не важно, как будет _называться_ это средство в данном конкретном ЯП

Важно. Язык С не является ОО языком, хотя в нем и возможно ООП. Можно называть «колоду перфокарт» процедурой, если угодно. Но пока в языке нет понятия процедуры - он не может называться процедурным.

svu ★★★★★
()
Ответ на: комментарий от svu

и в этом случае первые версии фортрана не были процедурными - там были рутины но небыло стека (даже бейсиковского GOSUB RETURN) - т.е без ручных манипуляций самим программистом не было возможности использовать процедурную декомпозицию.

qulinxao ★★☆
()
Ответ на: комментарий от svu

Важно.

Нет, не важно. От названия ничего не зависит, главное сущность и семантика объекта.

. Язык С не является ОО языком, хотя в нем и возможно ООП.

В нем не возможно ООП. В нем можно писать в процедурном стиле, который _будет похож_ на ООП. Вот если бы в сишке были макросы (настоящие), то было бы возможно ООП.

Но пока в языке нет понятия процедуры - он не может называться процедурным.

Да не нужно никому понятий. Понятие - это лишь то, как люди договорились называть некоторый объект. Это субъективное качество, которое зависит от человека. Важно, чтобы в языке был объект, который соответсовал определнию процедуры. При этом называться он может подругшому. Вот в сишке нету объектов, которые бы соответствовали определению класса. И сделать нельзя. По-этому сишка - не ООП. А набор перфокарт соответствует определению процедуры.

anonymous
()
Ответ на: комментарий от qulinxao

Еще раз - для процедурной декомпозиции никакого стека не нужно. С чего вообще вам пришло в голову, что между процедурами и стеком есть какая-то связь?

anonymous
()
Ответ на: комментарий от anonymous

для индукции (процедурной) придётся в ручную организовывать вложенности возвратов вот и всё.

перве рутины и были по сути вынесенной в общую библиотеку копипастой с известным юзерам адресом входа известной областью над которым эта рутина изгаляется и опят же известным местом куда вызываюший должен оставить адрес по которому рутина перейдёт по завершению - стек не нужен .

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

qulinxao ★★☆
()
Ответ на: комментарий от anonymous

для складывания дерева - стек не нужен потому что дерево можно линейным путём обойти .

а вот если решение содержит в себе «разделяй и властвуй» с сылкой на себя(прямую или косвенную) то в каком либо виде FIFO список кем либо будет менеджится.

qulinxao ★★☆
()

Сноски не читаешь? Зря, там есть ответ на твой вопрос.

anonymous
()
Ответ на: комментарий от qulinxao

а вот если решение содержит в себе «разделяй и властвуй» с сылкой на себя(прямую или косвенную) то в каком либо виде FIFO список кем либо будет менеджится.

Это тут при чем?

anonymous
()
Ответ на: комментарий от anonymous

От названия ничего не зависит

Зависит. Одну ту же сущность можно рассматривать под разными углами.

В нем не возможно ООП

gobject- это ООП. winapi - это ООП. Уровень vfs/vnode в линухе - это ООП.

Понятие - это лишь то, как люди договорились называть некоторый объект

Это то, как люди ДУМАЮТ о нем. И из этого вытекает то, как они могут это применять. Есть такое слово ПАРАДИГМА, вот оно как раз об этом. И именно о парадигмах ПП и ФП я говорю.

По-этому сишка - не ООП

Сишка - не ООЯ. Но в нем возможно ООП. Если в каком-то языке нет концепции АБВГД, может оказаться, что можно его закрутить так, чтобы программировать в стиле АБВГД. Но сам язык не будет языком АБВГДистым.

А набор перфокарт соответствует определению процедуры.

Есть предложение забыть про перфокарты, ибо они вообще не язык, а носитель. На них можно много чего наклепать. Тот же Фортран.

svu ★★★★★
()
Последнее исправление: svu (всего исправлений: 1)
Ответ на: комментарий от anonymous

не точен.

да. достаточно индексируемой памяти - всё остальное (подобно взводу солдат с лобзиками способными вытачить любого профиля гребной вал для субмарины) в руках демиургапрограммиста.

но со стеком как то частные задачи решались проще.

правда ограничили себя , что функции не первого класса.

qulinxao ★★☆
()
Ответ на: комментарий от pseudo-cat

Если у нас есть _объекты_ типа X, то (элементарными) _операциями_ над такими объектами будут, например, тотальные функции X -> X (унарные) и X * X -> X (бинарные), такие объекты и операции образуют какую-то алгебраическую структуру, например моноид в случае X = List и конкатенации (вообще — какая-то универсальная алгебра). Если применить операцию к объекту(ам) — получится снова объект.

Теперь пусть эти операции будут новыми «объектами», а новыми «операциями» будут их _композиции_, например для унарных есть compose/fmap — (X -> X) * (X -> X) -> (X -> X) и apply/id — (X -> X) -> (X -> X) ~ (X -> X) * X -> X, для унарных и бинарных есть bind/ap — (X -> X) * (X * X -> X) -> (X -> X), join — (X * X -> X) -> (X -> X), для бинарных есть kleisli — (X * X -> X) * (X * X -> X) -> (X * X -> X) и т.п. Если применить композицию к операции(ям) — получится новая (сложная) операция.

Вот я спрашивал какую математическую структуру образуют операции-над-объектами и композиции-операции (просто сами объекты и замкнутые операции — какую-то универсальную алгебру) — как минимум apply и compose образуют категорию стрелок-функций над данным объектом-типом с обычным применением и композицией функций (+ есть функтор (->) _ : * -> * на категории типов и функций вообще который превращает стрелки (a -> b) в стрелки (_ -> a) -> (_ -> b) частичной композицией функции), а bind/ap/join — части некой монадической структуры над стрелками-функциями из данного-объекта типа (с соответствующей Kleisli категорией).

З.Ы. compose f g = \x -> f (g x), apply f = \x -> f x, join f = \x -> f x x, bind f g = \x -> f (g x) x = join (compose f g), ap f g = \x -> f x (g x) = join (compose (flip f) g), kleisli f g = \x y -> f y (g x y) = compose (ap f) g.

quasimoto ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.