Автор Тема: Замыкания  (Прочитано 13307 раз)

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Замыкания
« : Май 11, 2012, 02:54:14 pm »
Стыдно признаться, но никак не могу понять зачем оно нужно. Как работает понимаю, а хде оно могло бы пригодиться не врубаюсь.

Где можно почитать по теме, чтоб вот сразу стало понятно что без них жить нельзя?

Ну или примерчик какой доходчивый не эзотерический.

Смотрел на руби и на жабаскрипте примеры, но профита не понял.

p.s. Али это все от лукавого?

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Замыкания
« Ответ #1 : Май 11, 2012, 03:03:33 pm »
Смотрел на руби и на жабаскрипте примеры, но профита не понял.

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

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Замыкания
« Ответ #2 : Май 11, 2012, 03:06:32 pm »
Я правильно понимаю, что если язык с ООП, то замыкания не нужны?

Ну т.е. мне не понятно нафиг его везде пихают.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Замыкания
« Ответ #3 : Май 11, 2012, 03:19:53 pm »
Я правильно понимаю, что если язык с ООП, то замыкания не нужны?

Ну т.е. мне не понятно нафиг его везде пихают.

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

Например, классическая функция сортировки. На входе элементы и функция сравнения. Теперь представь, что для того, чтобы реализовать функцию сравнения (сравнение двух элементов) тебе недостаточно знать сравниваемые элементы (которые передаются как аргументы), а нужен еще какой-то дополнительный контекст. Как получить доступ к этому контексту из функции? Можно через глобальную переменную, можно добавить ссылку на контекст в сам элемент. Но это очень некрасиво. ООП решение - функция сортировки принимает объект, у которого будет вызываться функция сравнения, в этот объект можно положить ссылку на контекст. В случае замыканий: в месте вызова функции сортировки к функции сравнения "привязывается" нужный контекст (как еще один аргумент или еще как).
« Последнее редактирование: Май 11, 2012, 03:22:19 pm от vlad »

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Замыкания
« Ответ #4 : Май 11, 2012, 03:31:24 pm »
Непонятно  :) Какой там может быть нужен контекст?
У меня мозг наверно как-то иначе пашет.  :(

Если не в лом, приведи пример кода с ООП и с замыканиями для сравнения пожалуйста.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Замыкания
« Ответ #5 : Май 11, 2012, 03:34:36 pm »
Непонятно  :) Какой там может быть нужен контекст?
У меня мозг наверно как-то иначе пашет.  :(

Если не в лом, приведи пример кода с ООП и с замыканиями для сравнения пожалуйста.

Пример на мерзком жабаскрипте:
function compate_using_context(elements, context)
{
    function compare(a, b) // наша функция сравнения
    {
        return context.eval(a) - context.eval(b); // context "виден" здесь, т.е. "привязан" к compare()
    }

    sort(elements, compare); // библиотечная функция sort(), ничего не знает про context
}

Попробуй подумать и написать тоже самое на обероне ;)

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Замыкания
« Ответ #6 : Май 11, 2012, 03:46:01 pm »
Любопытно. А контекст в данном случае это что? Объект ведающий о типах a, b?

Разве сама коллекция не имеет метода compare?
« Последнее редактирование: Май 11, 2012, 03:48:33 pm от ilovb »

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Замыкания
« Ответ #7 : Май 11, 2012, 03:52:34 pm »
Я дико извиняюсь конечно за назойливость.
Просто дюже хочется понять, а сколько попыток не предпринимал все никак.

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Замыкания
« Ответ #8 : Май 11, 2012, 03:59:57 pm »
Я вот приведу пару примеров (что сразу нагуглились)
function counter()
{
   var num = 0;
   return function()
   {
      return ++num;
   }
}

var c = counter();

c(); //1
c(); //2
c(); //3

type
  TGenericFunction = reference to function: string;
 
function Factory(const ASomeText: string):TGenericFunction;
begin
  Result := function: string
    begin
      Result := ASomeText;
    end;
end;
 
var
  f1, f2: TGenericFunction;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  f1 := Factory('First');
  f2 := Factory('Second');
 
  Memo1.Lines.Add(f1);
  Memo1.Lines.Add(f2);
end;

Кому как. По мне так примеры абсолютно сферические  ;D

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Замыкания
« Ответ #9 : Май 11, 2012, 04:01:19 pm »
Любопытно. А контекст в данном случае это что? Объект ведающий о типах a, b?

Да, например, он знает как их сравнивать.

Разве сама коллекция не имеет метода compare?

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

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Замыкания
« Ответ #10 : Май 11, 2012, 04:14:49 pm »
Хм... Тогда мне не понятны две вещи:
1. Если коллекция однородная, то ее в любом случае нужно наследовать и уточнять, и естественно нужно перегружать метод.
2. Для context этот метод ведь тоже нужно написать. А какая разница где я его напишу?

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Замыкания
« Ответ #11 : Май 11, 2012, 04:22:08 pm »
Хотя вот тут в принципе понятно:
int[] ary = { 1, 2, 3 };
 int x = 2;
 var ary1 = Array.ConvertAll<int, int>(ary, delegate(int elem) { return elem * x; }); // { 2, 4, 6 }
 // or..
 var ary2 = Array.ConvertAll<int, int>(ary, elem => { return elem * x; }); // { 2, 4, 6 }

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

Конкретно профит в том, что можно так написать: "{ return elem * x; }"

И кстати в Руби профит вроде в том же заключается. Но при чем тут замыкания?
« Последнее редактирование: Май 11, 2012, 04:26:38 pm от ilovb »

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Замыкания
« Ответ #12 : Май 11, 2012, 04:28:46 pm »
Конкретно профит в том, что можно так написать "{ return elem * x; }"

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

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Замыкания
« Ответ #13 : Май 11, 2012, 04:31:59 pm »
Хм... Тогда мне не понятны две вещи:
1. Если коллекция однородная, то ее в любом случае нужно наследовать и уточнять, и естественно нужно перегружать метод.

Э... зачем? Все элементы - наследники какого-нибудь Object и вперед.

2. Для context этот метод ведь тоже нужно написать. А какая разница где я его напишу?

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

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Замыкания
« Ответ #14 : Май 11, 2012, 04:35:55 pm »
Цитата: vlad
Нет, самый большой профит в том, что можно сослаться на локальную переменную x (тот самый контекст). Если бы у тебя не было замыкания - тебе пришлось что-то придумывать, чтобы использовать x в отдельной неанонимной функции.

Ну в паскалях например так не напишешь. Это ведь не фича замыкания, а фича самого языка.

Я про то, что в данном примере этот х явно в месте вызова записан.

Ну то есть фича лишь опирается на замыкания. Или, иначе говоря, фича невозможна без замыканий.
Но профит на мой взгляд тут именно в этой фиче, а не в замыкании.

Если в языке нет такой формы записи анонимных делегатов, то и профита из додиезовского примера не будет.
« Последнее редактирование: Май 11, 2012, 04:37:56 pm от ilovb »