Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2011.09.18;
Скачать: [xml.tar.bz2];

Вниз

Замыкания в Delphi.   Найти похожие ветки 

 
IPranker ©   (2011-05-26 02:35) [0]

В Dephi 2009 они появились:
http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%BC%D1%8B%D0%BA%D0%B0%D0%BD%D0%B8%D0%B5_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29#.D0.9F.D1.80.D0.B8.D0.BC.D0.B5.D1.87.D0.B0.D0.BD.D0.B8.D1.8F

Просьба объяснить где их применение очень облегчит написания кода,
а то тамошний пример ничего этого не отражает.


 
Юрий Зотов ©   (2011-05-26 04:26) [1]


> IPranker ©   (26.05.11 02:35)  
> В Dephi 2009 они появились

Где-то лет на 30 раньше.


 
Ega23 ©   (2011-05-26 08:08) [2]


> В Dephi 2009 они появились:

Они появились раньше, см. Pascal в твоей статье.


 
Димка На   (2011-05-26 08:37) [3]

В delphi - хз, в JavaScript - повсеместно


 
OW ©   (2011-05-26 08:39) [4]

как хитро обозвали то..
так юзаешь - юзаешь, и не знаешь что :)


 
Ega23 ©   (2011-05-26 08:40) [5]

В D2010 замыкание сразу в параметрах процедуры можно передать


 
KSergey ©   (2011-05-26 08:54) [6]

> Ega23 ©   (26.05.11 08:40) [5]

А можно пример?
Просто пример кода, любой


 
oxffff ©   (2011-05-26 09:11) [7]

Здесь хорошие примеры.
http://edn.embarcadero.com/cs/print/33336


 
RWolf ©   (2011-05-26 09:15) [8]


> Где-то лет на 30 раньше.

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


 
TUser ©   (2011-05-26 12:24) [9]


> Просьба объяснить где их применение очень облегчит написания
> кода,

Дело в том, что понятие "функция/процедура" едино в двух лицах. С одной стороны - снаружи - это черный ящик с параметрами и выхлопом, и снаружи мы видим ряды этих черных ящиков, и ими пользуемся. Разумеется, удобство пользования складом с ящиками не в последнюю очередь зависит от того, как эти ящики организованы, каталогизированы, документированы и пр. Чем их больше, тем сложнее описать. На описание документирование надо много времени. На чтение документации - тоже. С точки зрения пользователя снаружи, чем меньше таких ящиков - тем лучше.

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

Ясно, что следствием первого взгляда является - делать функций поменьше. Второго - побольше. Сабж (я всегда думал, что это называется "локальные функции" по аналогии с локальными переменными, но, видать, ошибался) - это разумный компромисс. Снаружи мы видим мало ящиков. Внутри мы можем структурировать некоторый кусок программы.

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


 
Dimka Maslov ©   (2011-05-26 12:48) [10]

В справке по Delphi это называется nested functions


 
Ega23 ©   (2011-05-26 12:49) [11]


> А можно пример?
> Просто пример кода, любой


 TMyClass<T> = class (TObject)
 public
   function Foo(Val1, Val2: T; aFunc: TFunc<T, T, T>): T;
 end;

function TMyClass<T>.Foo(Val1, Val2: T; aFunc: TFunc<T, T, T>): T;
begin
 Result := aFunc(Val1, Val2);
end;


использование:

procedure TForm10.Button4Click(Sender: TObject);
var
 myObj: TMyClass<Integer>;
 res: Integer;
begin
 myObj := TMyClass<Integer>.Create;
 try
   res := myObj.Foo(3, 2, function (v1, v2: Integer): Integer begin Result := v1 + v2; end);
   ShowMessage(IntToStr(res));
   res := myObj.Foo(3, 2, function (v1, v2: Integer): Integer begin Result := v1 - v2; end);
   ShowMessage(IntToStr(res));
   res := myObj.Foo(3, 2, function (v1, v2: Integer): Integer begin Result := v1 * v2; end);
   ShowMessage(IntToStr(res));
 finally
   myObj.Free;
 end;
end;



 
Ega23 ©   (2011-05-26 12:55) [12]


> Ega23 ©   (26.05.11 12:49) [11]


Ещё использование:

procedure TForm10.Button5Click(Sender: TObject);
var
 myObj: TMyClass<string>;
 s: string;
begin
 myObj := TMyClass<string>.Create;
 try
   s := myObj.Foo("delphi", "master", function (v1, v2: string): string begin result := "http://www." + v1 + v2 + ".ru" end);
   ShowMessage(s);
 finally
   myObj.Free;
 end;
end;


 
Ega23 ©   (2011-05-26 12:57) [13]

или

procedure TForm10.Button5Click(Sender: TObject);
var
myObj: TMyClass<string>;
s: string;
begin
myObj := TMyClass<string>.Create;
try
  s := myObj.Foo("delphi", "master", function (v1, v2: string): string begin if v1=v2 then exit("Match") else exit("Fail") end);
  ShowMessage(s);
finally
  myObj.Free;
end;
end;


 
Ega23 ©   (2011-05-26 13:15) [14]

З.Ы. Не надо ничего писать про "а в чём смысл такого класса?". В данном случае он действительно бессмысленный, просто демонстрация.


 
RWolf ©   (2011-05-26 13:19) [15]

> [9]
У паскалевских вложенных функций и у замыканий совершенно разное назначение. Замыкание — фактически, аналог экземпляра класса с одним методом, т.е. процедура и захваченный ей контекст, расположенный в куче.


 
TUser ©   (2011-05-26 13:27) [16]

то-то меня в вики удивили обороты типа "создается экземпляр функции"


 
Kerk ©   (2011-05-26 13:31) [17]


> Ega23 ©   (26.05.11 12:49) [11]

Это не замыкания. Это анонимные функции обычные.


 
Ega23 ©   (2011-05-26 13:31) [18]


> Это не замыкания. Это анонимные функции обычные.


Ну да, перепутал.


 
KSergey ©   (2011-05-26 13:43) [19]

> Ega23 ©   (26.05.11 13:15) [14]
> З.Ы. Не надо ничего писать про "а в чём смысл такого класса?

Сказал бы я что про все это думаю, но в приличных словах не получается :)
(я не про конкретные примеры)


 
DiamondShark ©   (2011-05-26 14:27) [20]


> RWolf ©   (26.05.11 13:19) [15]

Замыкание -- это захват контекста.
Каким образом оно будет сделано -- созданием объекта в куче или ссылкой на внешний стековый фрейм -- это детали реализации.
Паскалевские вложенные функции -- одна из множества возможных реализаций замыканий.


 
IPranker ©   (2011-05-26 17:10) [21]

Хм, т.е. по простому замыкания это вложенные функции?

Ссылка, приведённая мною выше не много нет та, хотя параграфы в Википедии одинаковы, примеры кода на Паскале разные. Страннно.

1)
http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%BC%D1%8B%D0%BA%D0%B0%D0%BD%D0%B8%D0%B5_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29#.D0.9F.D1.80.D0.B8.D0.BC.D0.B5.D1.87.D0.B0.D0.BD.D0.B8.D1.8F

2)
http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%BC%D1%8B%D0%BA%D0%B0%D0%BD%D0%B8%D0%B5_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29


 
IPranker ©   (2011-05-26 17:12) [22]

Что-то ссылки опять одинаковые получились.
Что там с Википедией твориться?
Надо так, вести в Гугле "Замыкания" и по ссылке в Википедию пройти.
Паскаль-пример будет на Дельфи с выводом в Мемо.


 
Kerk ©   (2011-05-26 17:30) [23]


> IPranker ©   (26.05.11 17:10) [21]
>
> Хм, т.е. по простому замыкания это вложенные функции?

Замыкание = функция + контекст.


 
han_malign   (2011-05-27 09:21) [24]


> Паскалевские вложенные функции -- одна из множества возможных
> реализаций замыканий.

- не-е-е, замыкание - это когда вложенная функция выполняется после завершения внешней...
http://ru.wikipedia.org/wiki/%D0%9B%D1%8F%D0%BC%D0%B1%D0%B4%D0%B0-%D0%B8%D1%81%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5#.D0.9A.D0.B0.D1.80.D1.80.D0.B8.D1.80.D0.BE.D0.B2.D0.B0.D0.BD.D0.B8.D0.B5_.28. D0.BA.D0.B0.D1.80.D1.80.D0.B8.D0.BD.D0.B3.29
http://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D1%80%D1%80%D0%B8%D0%BD%D0%B3

Для императивного программирования - это все синтаксический сахар с элементами запугивания...

Хотя, если реализация сделана наподобие низкоуровневого Classes.MakeObjectInstance - может быть весьма полезно при работе с кривыми реализациями callback-ов(без передачи контекста)...
Но что-то у меня большие сомнения, что на делегат можно просто так asm call сделать...


 
oxffff ©   (2011-05-27 09:32) [25]

Пора внести ясность.
Вообще есть небольшая путаница между closure и анонимными методами.
Это аналоги.

Anonymous Methods in Delphi

As the name suggests, an anonymous method is a procedure or function that does not have a name associated with it. An anonymous method treats a block of code as an entity that can be assigned to a variable or used as a parameter to a method. In addition, an anonymous method can refer to variables and bind values to the variables in the context in which the method is defined. Anonymous methods can be defined and used with simple syntax.
They are similar to the construct of closures defined in other languages.


 
KSergey ©   (2011-05-27 10:12) [26]

> han_malign   (27.05.11 09:21) [24]
> - не-е-е, замыкание - это когда вложенная функция выполняется после завершения внешней...

Хм, как-то я не увидел по приведенным ссылкам почему непременно после завершения. Плохо смотрел?


 
Romkin ©   (2011-05-27 12:59) [27]

http://blogs.teamb.com/craigstuntz/2008/08/28/37831/


 
jack128_   (2011-05-27 21:13) [28]


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

это не обязательно, но возможно.  Для вложенных функций такое - невозможно в принципе.


 
KSergey ©   (2011-05-28 13:00) [29]

> jack128_   (27.05.11 21:13) [28]
> это не обязательно, но возможно.  Для вложенных функций такое - невозможно в принципе.

Почему?! что именно не возможно? выполнить вложенную после окончания?

Более того, у han_malign   (27.05.11 09:21) [24] выполнение "после завершения" было названо основным свойством этого самого замыкания, но у jack128_   (27.05.11 21:13) [28] указывается, что это вовсе не обязательно...

Што ж это за заумы-то такие, что согласия в трактовке их совершенно нет?


 
DiamondShark ©   (2011-05-29 12:35) [30]


> han_malign   (27.05.11 09:21) [24]

Ну, если стоит вопрос о том, кто кого перевикипедит, то вотЪ:

http://ru.wikipedia.org/wiki/Замыкание_(программирование)

> Замыкание (англ. closure) в программировании — процедура,
>  которая ссылается на свободные переменные в своём лексическом
> контексте.
>
> Замыкание, так же как и экземпляр объекта, есть способ представления
> функциональности и данных, связанных и упакованных вместе.
>
> Замыкание — это особый вид функции. Она определена в теле
> другой функции и создаётся каждый раз во время её выполнения.
>  В записи это выглядит как функция, находящаяся целиком
> в теле другой функции. При этом вложенная внутренняя функция
> содержит ссылки на локальные переменные внешней функции.
>  Каждый раз при выполнении внешней функции происходит создание
> нового экземпляра внутренней функции, с новыми ссылками
> на переменные внешней функции.
>
> Замыкание связывает код функции с её лексическим окружением
> (местом, в котором она определена в коде). Лексические переменные
> замыкания отличаются от глобальных переменных тем, что они
> не занимают глобальное пространство имён. От переменных
> в объектах они отличаются тем, что привязаны к функциям,
>  а не объектам.

Ни слова о выполнении после внешней. Что вполне естественно, так так определяющее свойство замыканий -- именно доступ к контексту. А всё остальное второстепенно.


> oxffff ©   (27.05.11 09:32) [25]
> Это аналоги.

Хреналоги.

Каждая селёдка -- рыба. Но не каждая рыба -- селёдка.
А у тебя рыба и селёдка -- это аналоги.
От корня "анал", наверное.


 
RWolf ©   (2011-05-29 16:43) [31]


> KSergey ©   (28.05.11 13:00) [29]
> Почему?! что именно не возможно? выполнить вложенную
> после окончания?

Да, нельзя вызывать вложенную функцию иначе, как из охватывающей.
Если попытаться создать на неё ссылку и вызвать её из другого места, она в общем случае сломает стек.
А вот замыкание можно вызвать откуда угодно, потому что его контекст скопирован, снабжён счётчиком ссылок и находится под присмотром менеджера памяти.


 
oxffff ©   (2011-05-29 22:54) [32]


> DiamondShark ©   (29.05.11 12:35) [30]
>
> > oxffff ©   (27.05.11 09:32) [25]
> > Это аналоги.
>
> Хреналоги.
>
> Каждая селёдка -- рыба. Но не каждая рыба -- селёдка.
> А у тебя рыба и селёдка -- это аналоги.
> От корня "анал", наверное.


Странно почему это Вас так задевает. Вам виднее от какого корня.

http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%BC%D1%8B%D0%BA%D0%B0%D0%BD%D0%B8%D0%B5_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)

Замыкание (англ. closure) в программировании — процедура, которая ссылается на свободные переменные в своём лексическом контексте.

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

Замыкание — это особый вид функции. Она определена в теле другой функции и создаётся каждый раз во время её выполнения. В записи это выглядит как функция, находящаяся целиком в теле другой функции. При этом вложенная внутренняя функция содержит ссылки на локальные переменные внешней функции. Каждый раз при выполнении внешней функции происходит создание нового экземпляра внутренней функции, с новыми ссылками на переменные внешней функции.


 
oxffff ©   (2011-05-29 23:00) [33]


> DiamondShark ©   (29.05.11 12:35) [30]


Общее у замыканий и анонимных методов:

1. процедура, которая ссылается на свободные переменные в своём  
  лексическом контексте
2. Она определена в теле другой функции
3. Создаётся каждый раз во время её выполнения

Ждем от Вас отличия.


 
oxffff ©   (2011-05-29 23:07) [34]


> DiamondShark ©   (29.05.11 12:35) [30]
> А у тебя рыба и селёдка -- это аналоги.


Почему же просто closure это из функциональных языков.
Анонимные методы из императивных.


 
Bless ©   (2011-05-30 13:20) [35]

имхо, анонимные методы - это вовсе не аналог замыканий.


> Общее у замыканий и анонимных методов:
>1. процедура, которая  ссылается на свободные переменные в своём      >лексическом  контексте
>2. Она определена в теле другой функции
>3. Создаётся каждый раз во время её выполнения


Это общее не у замыканий и анонимных методов, а у процедур и анонимных методов. И те, и те могут ссылать на свободные переменные и быть определенными в теле других функций. А про "создается каждый раз" - это, имхо, вопрос реализации, вообще не принципиальный и, как по мне, еще и спорный.

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

Кстати, пункт 2 - должен звучать таки как "могут быть в теле другой функции". Вот простенький пример на Scheme, где нет "материнской" функции, и тем не менее есть замыкание.


(define f
 (let ((counter 0))
   (lambda ()
     (display counter)
     (newline)
     (set! counter (+ counter 1)))))


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


>
> Почему же просто closure это из функциональных языков.
> Анонимные методы из императивных.


Аналогом анонимных методов (из Delphi) в функциональных языках будет не closure, а лямбда.


 
Bless ©   (2011-05-30 13:40) [36]

Хотя. похоже, я воспринимаю замыкания несколько не так, как в википедии (процедура + контекст), и, вероятно, я не прав :)


 
KSergey ©   (2011-05-30 14:05) [37]

> RWolf ©   (29.05.11 16:43) [31]
> Да, нельзя вызывать вложенную функцию иначе, как из охватывающей.

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



Страницы: 1 вся ветка

Форум: "Прочее";
Текущий архив: 2011.09.18;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.003 c
15-1306699762
LDV
2011-05-30 00:09
2011.09.18
распознавание текста


2-1306609152
Cramol
2011-05-28 22:59
2011.09.18
Представить файл в HEX-виде


15-1306320156
clickmaker
2011-05-25 14:42
2011.09.18
Как в ICQ 7.5 отключить открытие по Ctrl+Shift+I


2-1306785926
R_R
2011-05-31 00:05
2011.09.18
Строка в DateTime.


2-1306830994
supergraf3000
2011-05-31 12:36
2011.09.18
просмотр html-кода





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский