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
Здравствуйте, Plague, Вы писали:
P>Если б эту статью уже выложили, а так какой толк сейчас?
А если почитать тред про эту статью, то можно найти вот такую ссылку
... << RSDN@Home 1.2.0 alpha rev. 655>>
"Бог не терпит голой сингулярности" -- Роджер Пенроуз
В этом форуме (да и в соседних тоже) часто упоминаются такие термины как 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 в различных языках (и частоту использования), а также поддержку этих понятий в различных языках (а при ее отсутствии — возможную реализацию).
Вопросы скорее теоретические, но мы же в "Философии" вроде находимся. Ой..., а может я не там вопросы задаю?
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?
Здравствуйте, FR, Вы писали:
FR>Между замыканиями и обычными функциями тоже различий никаких, любая функция может быть и замыканием.
Скажу больше. Как это не странно любой экземлярный метод замыкается на экзепляр своего лкасса. И замыкания можно без проблем эмулировать созданием классов. Впрочем как преобразованием функций.
В общем, ООП и ФП теоритически связаны. Осталось описать эту теорию.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Beam, Вы писали:
B>В этом форуме (да и в соседних тоже) часто упоминаются такие термины как Closure, Lambda, Currying. B>У меня так и не сложилось четкого представления об этих вещах. И думаю, что я такой не один.
Здравствуйте, CiViLiS, Вы писали:
CVL>Здравствуйте, Plague, Вы писали:
P>>Если б эту статью уже выложили, а так какой толк сейчас? CVL>А если почитать тред про эту статью, то можно найти вот такую ссылку
Надеюсь, ты понимаешь, чем отличается полтора экрана полезного материала от нудного разглагольствования на 15 страниц текста?
CiViLiS,
P>>Если б эту статью уже выложили, а так какой толк сейчас? CVL>А если почитать тред про эту статью, то можно найти вот такую ссылку
Статья неплохая , но там лямбды, карринг и замыкания даются в нетрадиционной для CS форме, то есть это совсем не определения, а выражение этих понятий через обычные понятия объекта и класса. Что впрочем, имхо, гораздо продуктивнее, чем зубрёжка определений.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Eugene Beschastnov, Вы писали:
EB>>Ну, если занудствовать, то пример вполне может служить доказательством — например, когда утверждается невозможность чего-либо.
VD>Если занудствовать, то это называется не доказательством, а опровержением.
Здравствуйте, 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>>- какие отличия между 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>Просто дай определения: лямбда — это ... и т.д.
А зачем?
Ищи в декларативном программирование, вроде были строгие определения.
Здравствуйте, 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. Ну откуда-то термины появились. Должны же быть однозначные определения.
Я не хочу развязывать спор. Я просто хочу знать.
Здравствуйте, 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>Не нашел. Может плохо искал. Поэтому и задал вопрос
Здравствуйте, 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>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.