Лямбда и замыкания для C++
От: vladimir_i СССР  
Дата: 10.08.10 13:41
Оценка: 1 (1)
Я старый C++ программист.
У меня не было хорошей возможности опробовать один тех языков, на которых в wiki объясняется практическое применение лямбд и замыканий.

Кто-нибудь может объяснить в чем же там суть с точки зрения C/C++?
Интересен даже гипотетический вариант кода, пусть даже невалидный, но объясняющий сабж.

Спсибо!
Re: Лямбда и замыкания для C++
От: SergH Россия  
Дата: 10.08.10 13:54
Оценка:
Здравствуйте, vladimir_i, Вы писали:

_>Я старый C++ программист.

_>У меня не было хорошей возможности опробовать один тех языков, на которых в wiki объясняется практическое применение лямбд и замыканий.

_>Кто-нибудь может объяснить в чем же там суть с точки зрения C/C++?

_>Интересен даже гипотетический вариант кода, пусть даже невалидный, но объясняющий сабж.

Лямбды это очень просто. Это возможность всунуть функцию куда угодно. Типа,

item = std::find_if(array.begin(), array.end(), lambda x: x % 3 == 2);


Слегка хитрее:

function(int p, int n) {

item = std::find_if(array.begin(), array.end(), lambda x: x % p == n);


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

Ну и там, конечно, лямбда может быть возвращаемым значением (так же как с С++ указатель на функцию), параметром и т.п.
Делай что должно, и будь что будет
Re: Лямбда и замыкания для C++
От: FR  
Дата: 10.08.10 14:04
Оценка: 2 (2)
Здравствуйте, vladimir_i, Вы писали:

_>Кто-нибудь может объяснить в чем же там суть с точки зрения C/C++?

_>Интересен даже гипотетический вариант кода, пусть даже невалидный, но объясняющий сабж.

http://www.rsdn.ru/article/funcprog/fp.xml#E3GAE
Автор(ы): Вячеслав Ахмечет
Дата: 16.09.2006
Данная статья достаточно кратко и вполне доступно, используя примеры на Java (!), знакомит читателя с базовыми понятиями функционального программирования.
Re: Лямбда и замыкания для C++
От: morm Россия  
Дата: 10.08.10 14:58
Оценка:
Здравствуйте, vladimir_i, Вы писали:

_>Я старый C++ программист.

_>У меня не было хорошей возможности опробовать один тех языков, на которых в wiki объясняется практическое применение лямбд и замыканий.

_>Кто-нибудь может объяснить в чем же там суть с точки зрения C/C++?

_>Интересен даже гипотетический вариант кода, пусть даже невалидный, но объясняющий сабж.

_>Спсибо!


в boost::lambda это выглядит так:

list<MClass*> m_cls;
...

for_each(m_cls.begin(), m_cls.end(), bind(_1->*&MClass::foo,"hello"));
или
remove_if(m_cls.begin(), m_cls.end(), _1->*&MClass::is_Working == constant(true));

и т.п. там есть и условный выбор и втраиваемые циклы, но имхо проще для этого функтор написать(тестировать и поддерживать проще)
Re: Лямбда и замыкания для C++
От: x-code  
Дата: 10.08.10 20:24
Оценка: 25 (9)
Здравствуйте, vladimir_i, Вы писали:

_>Кто-нибудь может объяснить в чем же там суть с точки зрения C/C++?

_>Интересен даже гипотетический вариант кода, пусть даже невалидный, но объясняющий сабж.

Лямбды — это функции, объявленные прямо в выражениях. Например, с таким синтаксисом
[ccode]
int sum = func(100,200,(x,y)=>x+y);
int mul = func(100,200,(x,y)=>x*y);
[/code]

Здесь выражения вида (x,y)=>x+y как раз и есть лямбда-функции. Разумеется, могут быть синтаксические нюансы — например, поскольку С++ типизирован, то может потребоваться явное указание типа. Вот, проследите за усложнением синтаксиса — от лямбды до обычного объявления функции:
 (x,y) => x+y;
 (int x, int y) => x+y
 lambda(int x, int y) { return x+y; }      // ключевое слово lambda
 int my_lambda_func(int x, int y) { return x+y; } // обычная функция Си

В C++0x, кстати, придумали другой синтаксис, с квадратными скобками.
В функцию func передается нечто вроде указателя на лямбду. Функция может при необходимости вызвать ее.

Замыкания — использование локальных переменных объемлющей функции внутри вложенной. Понятие замыкания относится как к лямбда-функциям, так и просто к вложенным функциям, которые возможны например в Паскале или в расширении Си gcc. Лямбды, понятное дело, являются частным случаем вложенных функций.

void outer_func()
{
  int x = 100;
  int inner_func()
  {
     return x + 10;   // использование локальной переменной
  }
}

Это бы вполне работало даже в чистом Си, если бы не возможость вернуть функцию наружу (через указатель на функцию, к примеру). Предположим, что outer_func возвращает указатель на свою вложенную функцию inner_func. Понятно, что эту возможность можно просто запретить. Или пойти тем путем как в Си — возврат адреса локальной переменной бессмысленен и никто так не делает. Но можно пойти до конца и реализовать функции как первоклассные объекты — т.е. чтобы с функциями можно было делать что угодо, в т.ч. возвращать из других функций.

Для этого нужно вместо возврата указателей на функции ввести понятие "делегаты" — специальные объекты, включающие в себя функцию и блок данных, необходимый для работы этой функции. Тогда, если бы oiter_func возвращала свою вложенную функцию, она могла бы возвращать делегат, содержащий, например, указатель на вложенную функцию и поле данных — переменную объемлющей функции. Вот псеводкод, который мог бы получиться при декомпиляции фрагмента с замыканием:
struct DELEGATE
{
  int (*fptr)();  // функция (хотя укзатель на функцию избыточен - достаточно просто объявить класс с функцией-членом)
  int x;          // блок данных; в нашем случае - переменная, "замкнутая" на функцию
};
DELEGATE outer_func()
{
  DELEGATE d;
  d.x = 100;
  int inner_func()
  {
     return d.x + 10;   // использование внешней локальной переменной
  }
  d.fptr = &inner_func;
  return d; // возвращаем функцию - ВМЕСТЕ и указатель, и внешняя локальная переменная! 
}

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

Все это, как видно, можно реализовать на С++ и в явном виде, причем без указателей на функции
struct DELEGATE // вложенная функция и переменная вынесены в отдельный класс
{
  int x;
  int inner_func()
  { 
    return x + 10;
  }
};
DELEGATE outer_func()
{ 
  DELEGATE d;
  d.x = 100;   
  return d;
}


Ясно что замыкания нужны как раз для лямбда-функций — поскольку лямбды кототкие и заточены для выполнения конкретной работы в конкретном месте кода, они вполне могут ссылаться на разные локальные переменные.
Re: Лямбда и замыкания для C++
От: Шахтер Интернет  
Дата: 10.08.10 21:24
Оценка:
Здравствуйте, vladimir_i, Вы писали:

_>Я старый C++ программист.

_>У меня не было хорошей возможности опробовать один тех языков, на которых в wiki объясняется практическое применение лямбд и замыканий.

_>Кто-нибудь может объяснить в чем же там суть с точки зрения C/C++?

_>Интересен даже гипотетический вариант кода, пусть даже невалидный, но объясняющий сабж.

_>Спсибо!


Вот иллюстративный пример.

/* main.cpp */ 

#include <CCore/inc/Print.h>

using namespace CCore;

template <class T,ulen Len,class F>
void Apply(T (&a)[Len],F f)
 {
  for(ulen i=0; i<Len ;i++) f(a[i]);
 }
 
/* main() */ 

int main()
 {
  int a[]={1,2,3,4,5};

  Apply(a, [] (int x) { Printf(Con,"#;\n",x); } );

  int s=0;

  Apply(a, [&] (int x) { s+=x; } );

  Printf(Con,"s = #; \n",s);

  return 0;
 }

1
2
3
4

5
s = 15

В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: Лямбда и замыкания для C++
От: CreatorCray  
Дата: 10.08.10 21:44
Оценка: +2 -1
Здравствуйте, x-code, Вы писали:

Мне кажется что стоит этот постинг поместить в FAQ.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Лямбда и замыкания для C++
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 12.08.10 04:49
Оценка:
CreatorCray,

CC>Мне кажется что стоит этот постинг поместить в FAQ.


Вот этот пост
Автор: Programmierer AG
Дата: 15.09.06
от Глеба гораздо полнее, имхо лучше его в факу.
Хотя и x-code всё правильно пишет.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[4]: Лямбда и замыкания для C++
От: CreatorCray  
Дата: 12.08.10 06:14
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Вот этот пост
Автор: Programmierer AG
Дата: 15.09.06
от Глеба гораздо полнее, имхо лучше его в факу.

Если в общем — то возможно и полнее.
Но применительно к С++ у x-code расписано сильно лучше.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Лямбда и замыкания для C++
От: vdimas Россия  
Дата: 12.08.10 07:24
Оценка: +1
Здравствуйте, x-code, Вы писали:

XC>Для этого нужно вместо возврата указателей на функции ввести понятие "делегаты" — специальные объекты, включающие в себя функцию и блок данных, необходимый для работы этой функции.


Терминологическая путаница. "Делегаты" — это функциональный объект, вызывающий другой код. Просто такой паттерн в ОО-системе, прямой наследник ОО-понятия "интерфейс" (не тот который interface в Java/C#, а который классический). Делегат необязательно бывает "лямбдой" с т.з. ФП.

В общем, "функциональный объект" вместе с необходимыми данными — это просто "функциональный объект", таков, какой он есть по своей природе. Через систему типов не функциональных языков описывается как ф-ия + необходимые данные к ней.

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


XC>[code]

XC>struct DELEGATE
XC>{
XC> int (*fptr)(); // функция (хотя укзатель на функцию избыточен — достаточно просто объявить класс с функцией-членом)
XC> int x; // блок данных; в нашем случае — переменная, "замкнутая" на функцию
XC>};

Это пример описание обычного функционального объекта в рамках языка С/С++, никакого не делегата, и далее у тебя его использование по декомпилированному коду тоже. Только функциональной чистоты ради переменную x надо было инициализировать в момент конструирования функционального объекта и объявить константной. В том то и фишка, что декомпилированный код, разумеется, будет содержать лишь "обычные функциональные объекты", коими умеет оперировать исполняющая среда, а "замыкание" — это не более чем синтаксическая помощь компилятора по определению таких ф-ных объектов по-месту.

XC>Ясно что замыкания нужны как раз для лямбда-функций — поскольку лямбды кототкие и заточены для выполнения конкретной работы в конкретном месте кода, они вполне могут ссылаться на разные локальные переменные.


Неважно, короткие лямбды или нет, для этого термина важен способ получения этих ф-ных объектов.
Re: Лямбда и замыкания для C++
От: Ka3a4oK  
Дата: 13.08.10 17:04
Оценка: :))) :))) :))
Здравствуйте, vladimir_i, Вы писали:

_>Я старый C++ программист.

И не знаю слов любви.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.