В этом форуме (да и в соседних тоже) часто упоминаются такие термины как Closure, Lambda, Currying.
У меня так и не сложилось четкого представления об этих вещах. И думаю, что я такой не один.
Интересно, что в языках, поддерживающих такие понятия, обычно не задумываешься где lambda, где closure и т.д. Просто используешь это все дело и все (блоки Smalltalk, Ruby, анонимные методы и делегаты в С#). Но т.к. термины все таки употребляются достаточно часто хотелось бы найти в сети/книгах (или совместными усилиями выработать) их понятное определение на русском языке.
А пока я опишу свое понимание. Пусть имеем лямбду
labmda(x) (x + n)
Здесь
x — связанная переменная, т.к. она является параметров функции
n — свободная переменная, она не является параметров функции и появляется из внешнего контекста.
Lambda:
— имеет свободны переменные (не определенные в контексте, но используемые внутри функци)
— при подстановке свободных переменных возвращает другую лямбду
Для того, чтобы определять функции на основе этой lambda создадим функцию:
В ней все переменные являются связанными и фактическа она аналогична обычной функции с параметрами. Т.к. все свободные переменные закрыты, эта функция называется closure.
Closure:
— не имеет свободных переменных, т.е. это "закрытая" лямбда
— при подстановке параметров возвращает обычный результат (не функцию)
— формируется из лямбды, путем закрытия свободных переменных
И это аналогично функции
funcAdd(x) (x + 3)
// пример использования
funcAdd(10) => результат 13
Остался карринг. Я понимаю его так: Currying:
— это процесс закрытия свободных переменных в лямбдах
Пусть есть лямбда
aLambda := lambda(p) (p + x + y) // x, y - свободные
xLambda := aLambda(1) => результат lambda(p) (p + 1 + y) // закрыли x, произошел карринг, получили другую лямбду
yLambda := xLambda(2) => результат lambda(p) (p + 1 + 2) // закрыли y, произошел карринг, теперь получили уже closure
Т.е. при карринге каждый раз мы закрываем по одной свободной переменной. Можно остановится, сформировав новую лямбду (xLambda в примере), а можно закрыть все свободные переменные и получить closure (yLamda в примере). Еще можно записать так:
yLambda := aLambda(1)(2) => результат lambda(p) (p + 1 + 2)
// использование
yLambda(25) => результат 28
Вопросы:
— правильны ли эти краткие определения терминов?
— какие отличия между closure и обычными (локальными) функциями?
— делегаты C# 1.0, анонимные методы 2.0 и "лямбды" в 3.0 это вовсе и не лямбды, а closure?
А может я все напутал, и вопросы заданы не правильно?
К сожалению, без конкретного определения терминов трудно обсуждать что-то еще, но очень хотелось бы поднять вопросы о практическом использования subject в различных языках (и частоту использования), а также поддержку этих понятий в различных языках (а при ее отсутствии — возможную реализацию).
Вопросы скорее теоретические, но мы же в "Философии" вроде находимся. Ой..., а может я не там вопросы задаю?
Здравствуйте, Beam, Вы писали:
B>В этом форуме (да и в соседних тоже) часто упоминаются такие термины как Closure, Lambda, Currying. B>У меня так и не сложилось четкого представления об этих вещах. И думаю, что я такой не один.
Здравствуйте, Plague, Вы писали:
P>Если б эту статью уже выложили, а так какой толк сейчас?
А если почитать тред про эту статью, то можно найти вот такую ссылку
... << RSDN@Home 1.2.0 alpha rev. 655>>
"Бог не терпит голой сингулярности" -- Роджер Пенроуз
Здравствуйте, CiViLiS, Вы писали:
CVL>Здравствуйте, Plague, Вы писали:
P>>Если б эту статью уже выложили, а так какой толк сейчас? CVL>А если почитать тред про эту статью, то можно найти вот такую ссылку
Надеюсь, ты понимаешь, чем отличается полтора экрана полезного материала от нудного разглагольствования на 15 страниц текста?
Здравствуйте, Beam, Вы писали:
B>А пока я опишу свое понимание.
B>Lambda: B>- имеет свободны переменные (не определенные в контексте, но используемые внутри функци)
Совсем не обязательно. Лямбда может совсем не иметь свободных переменных:
lambda х, у: х+у
B>- при подстановке свободных переменных возвращает другую лямбду
Что это значит я вообще не понял. Куда подставляются свободные переменные?
Надо проще быть. Я лично для себя определил так: лямбда — это банальная функция, не больше не меньше и есть ли у нее свободные переменные уже не важно.
B>Closure: B>- при подстановке параметров возвращает обычный результат (не функцию)
Почему функция не может быть обычным результатом?
B>- не имеет свободных переменных, т.е. это "закрытая" лямбда B>- формируется из лямбды, путем закрытия свободных переменных
Вот это уже ближе.
Действительно, замыкания с лямбдами тесно связаны. Замыкание — это функция которая имеет ссылки на свободные переменные. Заметь, она "закрывается" не значениями (как я думал еще вчера , привет АВК и Ллойду ), а ссылками на свободные переменные.
B>Currying: B>- это процесс закрытия свободных переменных в лямбдах
Нет. Карринг — это процесс закрытия связаных переменных.
inc = (1+) -- тут каррировали (почти кастрировали, кстати, почти одно и тоже) функцию + (имеющюю 2 параметра), теперь получили функцию inc с одним параметром.
B>Вопросы: B>- правильны ли эти краткие определения терминов?
см. выше B>- какие отличия между closure и обычными (локальными) функциями?
см. выше B>- делегаты C# 1.0, анонимные методы 2.0 и "лямбды" в 3.0 это вовсе и не лямбды, а closure?
Да, кстати, тут уже приводили ссылку на статью Lazy Cjow Rhrr, и скорее всего там это все описано гораздо правильней, подробней и ясней, но я принципиально не читал ее, т.к. заказал журнал и жду, когда тот придет, чтоб прочитать в нем
Здравствуйте, buriy, Вы писали:
P>>>Если б эту статью уже выложили, а так какой толк сейчас? CVL>>А если почитать тред про эту статью, то можно найти вот такую ссылку B>Надеюсь, ты понимаешь, чем отличается полтора экрана полезного материала от нудного разглагольствования на 15 страниц текста?
Юрик, тебя в универе 5 лет учили отделять море нудного разглагольствования от грамма полезного
Да и вряд ли можно даже о таких понятиях карринг, замыкания и особенно лямбда разглагольствовать на 15ти! страницах.
B>Lambda: B>- имеет свободны переменные (не определенные в контексте, но используемые внутри функци) B>- при подстановке свободных переменных возвращает другую лямбду
Лямбда на практике просто безымянная функция и ничего больше Без всяких надуманных тобой ограничений.
B>Closure: B>- не имеет свободных переменных, т.е. это "закрытая" лямбда B>- при подстановке параметров возвращает обычный результат (не функцию) B>- формируется из лямбды, путем закрытия свободных переменных
Замыкание это просто функция которая помнит контекст в котором определена, она вообще не связана с лямбдой, например может быть простой функцией.
B>Т.е. при карринге каждый раз мы закрываем по одной свободной переменной. Можно остановится, сформировав новую лямбду (xLambda в примере), а можно закрыть все свободные переменные и получить closure (yLamda в примере). Еще можно записать так:
Карринг просто удобный способ получить новую ФВП.
B>Вопросы: B>- правильны ли эти краткие определения терминов?
по моему нет.
B>- какие отличия между closure и обычными (локальными) функциями?
В языках где функции первоклассные объекты различий обычно никаких. Это просто упрощенный способ объявления функции.
B>- делегаты C# 1.0, анонимные методы 2.0 и "лямбды" в 3.0 это вовсе и не лямбды, а closure?
B>>- какие отличия между closure и обычными (локальными) функциями?
FR>В языках где функции первоклассные объекты различий обычно никаких. Это просто упрощенный способ объявления функции.
Это я тут про лямбду
Между замыканиями и обычными функциями тоже различий никаких, любая функция может быть и замыканием.
Здравствуйте, ie, Вы писали:
B>>Lambda: B>>- имеет свободны переменные (не определенные в контексте, но используемые внутри функци)
ie>Совсем не обязательно. Лямбда может совсем не иметь свободных переменных: ie>
ie>lambda х, у: х+у
ie>
ОК.
B>>- при подстановке свободных переменных возвращает другую лямбду
ie>Что это значит я вообще не понял. Куда подставляются свободные переменные?
Под подстановкой я имею ввиду их связывание с контекстом. Т.е. привязку их к реальным переменным/значениям.
ie>Надо проще быть. Я лично для себя определил так: лямбда — это банальная функция, не больше не меньше и есть ли у нее свободные переменные уже не важно.
Пусть будет так.
Lambda (лямбда) — это функция, которая может иметь свободные переменные (т.е. переменные, используемые в функции, но не являющимися ее параметрами).
lambda (x) (x) => lambda, нет свободных переменных
lamda (x, p) (x + p) => тоже lambda, есть свободные переменные - p
B>>Closure: B>>- при подстановке параметров возвращает обычный результат (не функцию)
ie>Почему функция не может быть обычным результатом?
Согласен. Я хотел сделать акцент на ризличиях Closure и Lambda.
Ведь обычно лямбды возвращает функцию, а closure — простое значение, не функцию.
Но действительно, это не всегда так.
B>>- не имеет свободных переменных, т.е. это "закрытая" лямбда B>>- формируется из лямбды, путем закрытия свободных переменных
ie>Вот это уже ближе.
ie>Действительно, замыкания с лямбдами тесно связаны.
Как раз и хотелось четко (однозначно) определить эту связь.
ie>Замыкание — это функция которая имеет ссылки на свободные переменные. Заметь, она "закрывается" не значениями (как я думал еще вчера , привет АВК и Ллойду ), а ссылками на свободные переменные.
Скорее, замыкание имеет привязанные к контексту ссылки (в противопоставление лямбде, где ссылки тоже есть, но они не привязаны).
Итак.
Closure (замыкание) — это лямбда (?), переменные которой связаны с внешним контекстом (т.е. всем (?) ее свободным переменным присвоены конкретные значения/ссылки, определенные вне этой функции).
define makeAdder(n) (
lambda(x) (x + n)
)
inc := makeAdder(1) // closure, в лямбде связали переменную n со значением 1
// получили функцию это равносильную этой:
define inc(x) (x+1)
Будет ли полученная функция замыканием, если не будут привязаны к контексту все свободные переменные.
define makeFunc(n) (
lambda(x) (x + n + k) // n, k - свободные
)
// в лямбде свяжем переменную n со значением 1
func := makeFunc(1)
// получили такую функцию:
define func(x) (x + 1 + k)
Как видно, мы получили другую лямбду. Но является ли это замыканием? Я думаю, да, т.к. связывание с контекстом все таки было.
Т.е. из определения выше, условие о связывании всех свободных переменных надо убрать?
Будет ли полученная функция замыканием, если будет присвоено конкретное значение параметрам функции:
define makeFunc(x) (
lambda(x, y) (x + y)
)
// в лямбде свяжем переменную x со значением 1
func := makeFunc(1)
// получили такую функцию:
define func(y) (1 + y)
Это тоже замыкание?
B>>Currying: B>>- это процесс закрытия свободных переменных в лямбдах
ie>Нет. Карринг — это процесс закрытия связаных переменных.
Не согласен. Тогда уж неважно, какие переменные связывать — свободные или переменные-параметры (связанных).
ie>
ie>inc = (1+) -- тут каррировали (почти кастрировали, кстати, почти одно и тоже) функцию + (имеющюю 2 параметра), теперь получили функцию inc с одним параметром.
ie>
Итак.
Карринг — процесс связывания переменных в лямбдах.
Т.е. карринг — процесс связывание, замыкание — результат
B>>Вопросы: B>>- правильны ли эти краткие определения терминов? ie>см. выше
Вы согласны с измененной формулировкой?
B>>- делегаты C# 1.0, анонимные методы 2.0 и "лямбды" в 3.0 это вовсе и не лямбды, а closure?
Если трактовать лямбды, как написано сейчас, тогда да — лямбды
P.S. Вообще-то я хотел поговорить именно о терминологии, т.е. получить/найти определения — лямбда, замыкание, карринг. Т.е. объяснение не на примерах, а именно определение терминов.
Здравствуйте, FR, Вы писали:
FR>Лямбда на практике просто безымянная функция и ничего больше Без всяких надуманных тобой ограничений.
Уже согласен
FR>Замыкание это просто функция которая помнит контекст в котором определена, она вообще не связана с лямбдой, например может быть простой функцией.
На мой взгляд, замыкание определяется (создается) в момент выполнения программы. И это основное отличие от обычной функции. И что значит "простой функцией"?
FR>Карринг просто удобный способ получить новую ФВП.
Здравствуйте, Beam, Вы писали:
ie>>Почему функция не может быть обычным результатом?
B>Согласен. Я хотел сделать акцент на ризличиях Closure и Lambda. B>Ведь обычно лямбды возвращает функцию, а closure — простое значение, не функцию. B>Но действительно, это не всегда так.
Давай лучше так. И лямбды и замыкания всегда возвращают результат (отсутствие результата, как обычно, будем считать результатом), а что является этим результатом, функция или значение, суть дела не меняет.
ie>>Действительно, замыкания с лямбдами тесно связаны. B>Как раз и хотелось четко (однозначно) определить эту связь.
замыкание ::= (лямбда + ссылки на свободные переменные) — так пойдет ?
ie>>Замыкание — это функция которая имеет ссылки на свободные переменные. Заметь, она "закрывается" не значениями (как я думал еще вчера , привет АВК и Ллойду ), а ссылками на свободные переменные.
B>Скорее, замыкание имеет привязанные к контексту ссылки (в противопоставление лямбде, где ссылки тоже есть, но они не привязаны).
Не согласен. См. ниже
B>Итак. B>
B>Closure (замыкание) — это лямбда (?), переменные которой связаны с внешним контекстом (т.е. всем (?) ее свободным переменным присвоены конкретные значения/ссылки, определенные вне этой функции).
B>
B>define makeAdder(n) (
B> lambda(x) (x + n)
B>)
B>inc := makeAdder(1) // closure, в лямбде связали переменную n со значением 1
B>// получили функцию это равносильную этой:
B>define inc(x) (x+1)
B>
Вот на этом примере давай остановимся. У тебя
lambda(x) (x + n)
является лямбдой, но не является замыканием. Почему?
define makeAdder() (
n := 1
l := lambda(x) (x + n)
l(3)
)
Вот в этом примере является замыканием?
B>Будет ли полученная функция замыканием, если не будут привязаны к контексту все свободные переменные.
B>
B>define makeFunc(n) (
B> lambda(x) (x + n + k) // n, k - свободные (***)
B>)
B>// в лямбде свяжем переменную n со значением 1
B>func := makeFunc(1) (+++)
B>// получили такую функцию:
B>define func(x) (x + 1 + k)
B>
B>Как видно, мы получили другую лямбду. Но является ли это замыканием? Я думаю, да, т.к. связывание с контекстом все таки было.
Является, только замыкание у нас опять появилось в (***), а не в (+++). Еще раз повторю: замыкание ссылается на свободные переменные, а не на значения.
B>Т.е. из определения выше, условие о связывании всех свободных переменных надо убрать?
Если у тебя k не является переменной лексического контекста в котом находится лямбда, то я вообще не уверен, что такой код скомпилируется.
B>Будет ли полученная функция замыканием, если будет присвоено конкретное значение параметрам функции:
B>
B>define makeFunc(x) (
B> lambda(x, y) (x + y)
B>)
B>// в лямбде свяжем переменную x со значением 1
B>func := makeFunc(1)
B>// получили такую функцию:
B>define func(y) (1 + y)
B>
B>Это тоже замыкание?
Я выделил замыкание.
B>>>Currying: B>>>- это процесс закрытия свободных переменных в лямбдах
ie>>Нет. Карринг — это процесс закрытия связаных переменных.
B>Не согласен. Тогда уж неважно, какие переменные связывать — свободные или переменные-параметры (связанных).
Ссылки на свободные мы получаем благодаря замыканию и карринг тут не причем.
ie>>
ie>>inc = (1+) -- тут каррировали (почти кастрировали, кстати, почти одно и тоже) функцию + (имеющюю 2 параметра), теперь получили функцию inc с одним параметром.
ie>>
B>Итак. B>
B>Карринг — процесс связывания переменных в лямбдах.
B>Т.е. карринг — процесс связывание, замыкание — результат B>Вы согласны с измененной формулировкой?
Нет. Не согласен.
Карринг — создание новой функции путем задания значений одному или более агрументу:
f n p = ... -- тут был тип функции a -> a -> a
g = f 1 -- тут получили с типом a -> a
Никакие свободные переменные тут не учавствуют и учавствовать не могут.
B>На мой взгляд, замыкание определяется (создается) в момент выполнения программы. И это основное отличие от обычной функции. И что значит "простой функцией"?
Простая в смысле первоклассная функция, именованная не лямбда. Какая разница когда создается? Главное то что помнит контекст.
FR>>Карринг просто удобный способ получить новую ФВП.
B>Просто дай определения: лямбда — это ... и т.д.
А зачем?
Ищи в декларативном программирование, вроде были строгие определения.
Beam wrote: > P.S. Вообще-то я хотел поговорить именно о терминологии, т.е.получить/найти определения — лямбда, замыкание, карринг. Т.е. объяснение не на примерах, а именно определение терминов.
В таком случае проще прочесть в Википедии.
Из-за того, что в лямбда-исчислении, функции прекрасно обходятся без имен, конструкции языков программирования, позволяющие в контексте выражения определить безымянную функцию/процедуру, часто называют лямбда-функциями, чаще всего неправомерно, просто по аналогии с Лиспом, в котором такая конструкция появилась впервые.
Карринг — простое преобразование, позволяющее свести все функции к функциям одного аргумента. Если язык программирования поддерживает функции высшего порядка, такое преобразование всегда можно выполнить вручную (Scheme):
(define foo_curried
(lambda (x)
(lambda (y)
(foo x y)))))
Языки, о которых говорят, что они поддерживают карринг, это преобразование делают автоматически, т.е. (Ocaml)
let foo x y z = expr
(* эквивалентно *)let foo =fun x -> fun y -> fun z -> expr
Здравствуйте, ie, Вы писали:
ie>Давай лучше так. И лямбды и замыкания всегда возвращают результат (отсутствие результата, как обычно, будем считать результатом), а что является этим результатом, функция или значение, суть дела не меняет.
ОК.
ie>замыкание ::= (лямбда + ссылки на свободные переменные) — так пойдет ?
Что такое ссылки на свободные переменные? Если имеется ввиду ссылки на переменные, определенные во внешнем контексте, то да, согласен.
Если нет — тогда что?
B>>Скорее, замыкание имеет привязанные к контексту ссылки (в противопоставление лямбде, где ссылки тоже есть, но они не привязаны).
ie>Не согласен. См. ниже
Может я не понят. Я имею ввиду, что в лямбде описаны свободные переменные (внешние), но их значения не определены. А вот в замыкания они имеют конкретные значения/ссылки, т.е. привязаны к контексту.
ie>Вот на этом примере давай остановимся. У тебя ie>
ie>lambda(x) (x + n)
ie>
ie>является лямбдой, но не является замыканием. Почему?
Не является замыканием, потому что не имеет ни одной переменной, привязанной к внешнему контексту. Его вообще здесь нет
ie>
ie>define makeAdder() (
ie> n := 1
ie> l := lambda(x) (x + n)
ie> l(3)
ie>)
ie>
ie>Вот в этом примере является замыканием?
Да. Сделана привязка переменной n (она реально существует). В данном случае контекст — makeAdder.
B>>Будет ли полученная функция замыканием, если не будут привязаны к контексту все свободные переменные.
B>>
B>>define makeFunc(n) (
B>> lambda(x) (x + n + k) // n, k - свободные (***)
B>>)
B>>// в лямбде свяжем переменную n со значением 1
B>>func := makeFunc(1) (+++)
B>>// получили такую функцию:
B>>define func(x) (x + 1 + k)
B>>
B>>Как видно, мы получили другую лямбду. Но является ли это замыканием? Я думаю, да, т.к. связывание с контекстом все таки было.
ie>Является, только замыкание у нас опять появилось в (***), а не в (+++).
Не спорю, замыкание появилось в (***). Именно там была создана новая функция. В (+++) всего лишь присваивание. См. чуть ниже
ie>Еще раз повторю: замыкание ссылается на свободные переменные, а не на значения.
И с этим я не спорю. Просто в примерах используются значения.
B>>Будет ли полученная функция замыканием, если будет присвоено конкретное значение параметрам функции:
B>>
B>>define makeFunc(x) (
B>> lambda(x, y) (x + y)
B>>)
B>>// в лямбде свяжем переменную x со значением 1
B>>func := makeFunc(1)
B>>// получили такую функцию:
B>>define func(y) (1 + y)
B>>
ie>Я выделил замыкание.
Не понял. Похоже ты называешь замыканием описание лямбды, расположенной в каком либо контексте, а я — называю замыканием конкретную функцию, которая существует в программе (ну как объект) и создается динамически. Я понятно разницу объяснил?
B>>>>Currying: B>>>>- это процесс закрытия свободных переменных в лямбдах
ie>>>Нет. Карринг — это процесс закрытия связаных переменных.
B>>Не согласен. Тогда уж неважно, какие переменные связывать — свободные или переменные-параметры (связанных).
ie>Ссылки на свободные мы получаем благодаря замыканию и карринг тут не причем.
ОК. см. ниже
ie>>>
ie>>>inc = (1+) -- тут каррировали (почти кастрировали, кстати, почти одно и тоже) функцию + (имеющюю 2 параметра), теперь получили функцию inc с одним параметром.
ie>>>
B>>Итак. B>>
B>>Карринг — процесс связывания переменных в лямбдах.
B>>Т.е. карринг — процесс связывание, замыкание — результат B>>Вы согласны с измененной формулировкой?
ie>Нет. Не согласен. ie>Карринг — создание новой функции путем задания значений одному или более агрументу: ie>
ie>f n p = ... -- тут был тип функции a -> a -> a
ie>g = f 1 -- тут получили с типом a -> a
ie>
ie>Никакие свободные переменные тут не учавствуют и учавствовать не могут.
Начал писать пример, почему это неправда. И пришел к выводу, что ты прав
Карринг относится только к параметрам функции и уменьшает количество опять же параметров, но никак не свободных (внешних) переменных.
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, Beam, Вы писали:
B>>На мой взгляд, замыкание определяется (создается) в момент выполнения программы. И это основное отличие от обычной функции. И что значит "простой функцией"?
FR>Простая в смысле первоклассная функция, именованная не лямбда. Какая разница когда создается? Главное то что помнит контекст.
FR>>>Карринг просто удобный способ получить новую ФВП.
B>>Просто дай определения: лямбда — это ... и т.д.
FR>А зачем? FR>Ищи в декларативном программирование, вроде были строгие определения.
Не нашел. Может плохо искал. Поэтому и задал вопрос
Здравствуйте, Трурль, Вы писали:
Т>Использование чужой терминологии в ИТ считается верхом неприличия, но «вообще говоря»:
Т>Лямбда-выражение – выражение с выделенными переменными-аргументами, обозначающее функцию этих агрументов.
а как же возможность обращаться к свободным переменным (не определенных в функции)?
Т>Замыкание – структрура данных для представления замкнутого функционального выражения.
Структура данных? Я думал, что замыкание — это функция.
Замкнутое выражение — это что?
Т>Карринг — представление функции нескольких переменных в виде функции, возвращающей функцию, возвращающую функцию и.т.д. по необходимости.
Ну вот. Карринг — это представление функцмм, или все-таки преобразование? Или и то, и другое.
P.S. Ну откуда-то термины появились. Должны же быть однозначные определения.
Я не хочу развязывать спор. Я просто хочу знать.
CiViLiS,
P>>Если б эту статью уже выложили, а так какой толк сейчас? CVL>А если почитать тред про эту статью, то можно найти вот такую ссылку
Статья неплохая , но там лямбды, карринг и замыкания даются в нетрадиционной для CS форме, то есть это совсем не определения, а выражение этих понятий через обычные понятия объекта и класса. Что впрочем, имхо, гораздо продуктивнее, чем зубрёжка определений.
Здравствуйте, Beam, Вы писали:
ie>>замыкание ::= (лямбда + ссылки на свободные переменные) — так пойдет ? B>Что такое ссылки на свободные переменные? Если имеется ввиду ссылки на переменные, определенные во внешнем контексте, то да, согласен.
Да, именно это с самого твоего первого поста и имелось ввиду.
B>>>Скорее, замыкание имеет привязанные к контексту ссылки (в противопоставление лямбде, где ссылки тоже есть, но они не привязаны). ie>>Не согласен. См. ниже B>Может я не понят. Я имею ввиду, что в лямбде описаны свободные переменные (внешние), но их значения не определены. А вот в замыкания они имеют конкретные значения/ссылки, т.е. привязаны к контексту.
Еще раз, как только в функции определены свободные переменные, она есть замыкание! Не может быть свободных переменных используемых в функции, если те не определены во внешнем контексте. Или я чего-то не знаю?
ie>>Вот на этом примере давай остановимся. У тебя ie>>
ie>>lambda(x) (x + n)
ie>>
ie>>является лямбдой, но не является замыканием. Почему?
B>Не является замыканием, потому что не имеет ни одной переменной, привязанной к внешнему контексту. Его вообще здесь нет
Угу, а что в таком случае n? Разве не свободная переменная? Безусловно, я этого явно не указал, но полагаю, что где-то во внешнем контексте она определена. Да и вообще у меня в голове не укладывается, что n может быть совсем нигде не определена. Ну тупо не скомпилиться/сыньтерпритируется код.
B>>>Будет ли полученная функция замыканием, если не будут привязаны к контексту все свободные переменные.
B>>>
B>>>define makeFunc(n) (
B>>> lambda(x) (x + n + k) // n, k - свободные (***)
B>>>)
B>>>// в лямбде свяжем переменную n со значением 1
B>>>func := makeFunc(1) (+++)
B>>>// получили такую функцию:
B>>>define func(x) (x + 1 + k)
B>>>
B>>>Как видно, мы получили другую лямбду. Но является ли это замыканием? Я думаю, да, т.к. связывание с контекстом все таки было. ie>>Является, только замыкание у нас опять появилось в (***), а не в (+++). B>Не спорю, замыкание появилось в (***). Именно там была создана новая функция. В (+++) всего лишь присваивание. См. чуть ниже
Создана новая функция.... Хмм... А при чем тут создана? Объявлена функция с ссылкой на свободные переменные.
ie>>Еще раз повторю: замыкание ссылается на свободные переменные, а не на значения. B>И с этим я не спорю. Просто в примерах используются значения.
В примерах используются переменные. Я там значений не увидел.
B>>>Будет ли полученная функция замыканием, если будет присвоено конкретное значение параметрам функции:
B>>>
B>>>define makeFunc(x) (
B>>> lambda(x, y) (x + y)
B>>>)
B>>>// в лямбде свяжем переменную x со значением 1
B>>>func := makeFunc(1)
B>>>// получили такую функцию:
B>>>define func(y) (1 + y)
B>>>
ie>>Я выделил замыкание.
B>Не понял. Похоже ты называешь замыканием описание лямбды, расположенной в каком либо контексте, а я — называю замыканием конкретную функцию, которая существует в программе (ну как объект) и создается динамически. Я понятно разницу объяснил?
Да, я считаю замыканием не экземпляр функции, а саму функцию, т.е. ее декларацию. А когда я работаю с функцией, которую мне вернули, то меня мало беспокоит замыкание это или нет.
P.S. А вообще тут уже правильно заметили, все определения есть в википедии. Насколько они формальны чудить не мне, но общую картину они дают, а чего же более желать.
Здравствуйте, Beam, Вы писали:
Т>>Лямбда-выражение – выражение с выделенными переменными-аргументами, обозначающее функцию этих агрументов.
B>а как же возможность обращаться к свободным переменным (не определенных в функции)?
Попиндикулярно.
Т>>Замыкание – структрура данных для представления замкнутого функционального выражения.
B>Структура данных? Я думал, что замыкание — это функция.
Функция — понятие синтаксиса и семантики языка, замыкание — реализации.
B>Замкнутое выражение — это что?
Замкнутое выражение — выражение, не содержащее свободных переменных.
B>Ну вот. Карринг — это представление функцмм, или все-таки преобразование? Или и то, и другое.
Тебе что, экзамен сдавать?
Допустим мы придумали функцию, определяющую сумму двух чисел. По смыслу это функция двух агрументов. Но в нашем языке все функции имеют ровно один агрумент. Что делать?
Если в языке есть кортежи, можно собрать аргументы в кортеж и получить функцию (x,y) -> x+y. Здесь подошло бы название tupling, но оно уже занято.
Если в языке есть функции высшего порядка, можно соорудить функцию x -> (y -> x+y). Вот здесь мы применили currying.
Здравствуйте, FR, Вы писали:
FR>Простая в смысле первоклассная функция, именованная не лямбда. Какая разница когда создается? Главное то что помнит контекст.
На самом деле контест может быть разным. Вот в D он статический. В Смолтоке... даже не берусь дать точное определение, наверно динамическо-статический. В C#, Nemerle, Scala, OСaml и по умолчанию в Лиспе он лексический, хотя в Лиспе он может быть динамическим.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Beam, Вы писали:
FR>>Ищи в декларативном программирование, вроде были строгие определения.
B>Не нашел. Может плохо искал. Поэтому и задал вопрос
Здравствуйте, FR, Вы писали:
FR>Между замыканиями и обычными функциями тоже различий никаких, любая функция может быть и замыканием.
Скажу больше. Как это не странно любой экземлярный метод замыкается на экзепляр своего лкасса. И замыкания можно без проблем эмулировать созданием классов. Впрочем как преобразованием функций.
В общем, ООП и ФП теоритически связаны. Осталось описать эту теорию.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, FR, Вы писали:
FR>>Между замыканиями и обычными функциями тоже различий никаких, любая функция может быть и замыканием.
VD>Скажу больше. Как это не странно любой экземлярный метод замыкается на экзепляр своего лкасса. И замыкания можно без проблем эмулировать созданием классов. Впрочем как преобразованием функций.
VD>В общем, ООП и ФП теоритически связаны. Осталось описать эту теорию.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Eugene Beschastnov, Вы писали:
EB>>Доказательство примером подойдёт? (часть "Aha! How to get rid of Objects in Smalltalk")
VD>Нет.
Обрати внимание на смайлик, скучный ты человек.
VD>Доказать примером ничего нельзя. Они могут описывать частный случай.
Ну, если занудствовать, то пример вполне может служить доказательством — например, когда утверждается невозможность чего-либо.
Здравствуйте, Eugene Beschastnov, Вы писали:
EB>Ну, если занудствовать, то пример вполне может служить доказательством — например, когда утверждается невозможность чего-либо.
Если занудствовать, то это называется не доказательством, а опровержением.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Eugene Beschastnov, Вы писали:
EB>>Ну, если занудствовать, то пример вполне может служить доказательством — например, когда утверждается невозможность чего-либо.
VD>Если занудствовать, то это называется не доказательством, а опровержением.