лямда в c11 польза или извращение?
я обычно лямды применяю с STL, там где раньше (до С11) предикаты применял.
Но вот обнаружил еще вариант:
void fun()
{
...
...
...[&]() // лямда функция
...{
... ...
...}();
....
}
там где точки может быть куча другого кода.
Как минимум одно оправдание такому коду я придумал - чтобы одним нажатием F10 (в ВизуалСтудии) весь код что в лямде перепрыгнуть. А может еще есть?
Это во всех языках - религия. Кому то нравится, кому то нет.
http://archive.kalnytskyi.com/2011/10/30/introduction-to-c...
в c# это изначально присутствует, пользуюсь иногда. когда нужно проделать что-то один раз, и хочется, чтобы было сразу тут, на месте видно, что именно проделывается, а не нужно лезть куда-то еще, чтобы посмотреть, что конкретно делает ф-я. при использовании linq иногда просто не знаю, как бы без ламбды обходиться. привыкнуть к форме записи нужно просто, тогда вопросы "зачем" не будут возникать. к макро в си привыкнуть вообще невозможно: привыкать нужно к каждой индивидуально и на каждую нужно лезь и смотреть, что она там выделывает, и не всегда правильно поймешь : )
Основное преимущество лямбды - это возможность захвата (capture) переменных. Некоторые вещи без лямбды невозможно реализовать в принципе (без кривых костылей).
можете наглядный пример вещи привести, которую невозможно без ламбды или костылей?
Классический пример - использование std::алгоритмов. Например, вам надо отсортировать вектор векторов по i-му элементу этих векторов, причём i задаётся во время выполнения. Алгоритм сортировки принимает два параметра, но нам надо передать три. Классическое решение с костылями - пишем функтор с конструктором, принимающим i как параметр, далее по схеме. Недостатки очевидны - функтор надо писать и мейнтейнить, во время дизайна определять, что передавать в конструктор и т.п. Типичный костыль в вакууме. Много кода, выхлопа мало. Лямбда решает все проблемы с помощью захвата контекста (по желанию автоматического) прямо при вызове алгоритма.
можете привести реальный РАБОТАЮЩИЙ код "с костылями" и без? для std::vector<std::vector<int> >
как туда втулить это i? чтобы было попроще и понагляднее.
Мне лень. На словах я объяснил, за деталями - добро пожаловать на stackoverflow.
вывод напрашивается, что в вашей практике пока еще не было случая, когда вы сперва попробовали костыли, оказались кривыми, не понравилось, и вы переделали все очень красиво и просто с помощью ламбды? откуда тогда мнение? и какова его цена?
Ваша способность делать выводы потрясающая. За сим откланиваюсь.
жаль, что вы решили стать в позу вместо потратить пять минут и привести пример кода (уже имеющегося, я так понимаю). послать на stackoverflow и отшаркаться - это проще всего, и не придает вашему мнению веса.
Классическое решение с костылями - пишем функтор с конструктором, принимающим i как параметр, далее по схеме. Недостатки очевидны - функтор надо писать и мейнтейнить, во время дизайна определять, что передавать в конструктор и т.п. Типичный костыль в вакууме. Много кода, выхлопа мало. Лямбда решает все проблемы с помощью захвата контекста (по желанию автоматического) прямо при вызове алгоритма.
Вопрос спорный.
Во-первых, лямбда нетестируема сама по себе. Т.е. если у тебя цикломатическая сложность лямбды больше 1, то привет.
Во-вторых, лямбда совершенно негибкая конструкция. Т.е. если у тебя в одном случае вектор векторов, а в другом вектор словарей, то придется тебе писать код два раза, вместо того, чтобы передать вектор + нужный функтор.
Во-третьих, если у тебя есть несколько мест с похожей сортировкой, то придется тебе лямбду дублировать.
Во-третьих, если у тебя есть несколько мест с похожей сортировкой, то придется тебе лямбду дублировать.я так понимаю, что если появилась нужда лямду дублировать, то нужно лямду обозвать как следует - т.е. сделать из нее нормальную функцию. НО! только если функция не чуть сложнее примитивной. Примитивные вещи можно даже в лямдах дублировать.
Да и вообще, на мой взгляд, удел лямд - чтото простенькое и маленькое.
с костылями:
struct P
{
__P(int i) : m_i(i){}
__bool operator < (vector& a, vector& b) {return a[ i ] < b[ i ];}
};
int i = 7;
vector<vector<int>> vv;
std::sort(vv.begin(), vv.end(), P(i));
с лямдой:
int i = 7;
vector<vector<int>> vv;
std::sort(vv.begin(), vv.end(), <&>(a, b){return a< i> < b< i>;} );
пардон, тут вместо квадратных скобок знаки больше и меньше зачастую. Потому как я сайт меня победил - я задолбался уже редактировать этот текст
при попытке редактировать сайт вообще половину текста выбрасывает! Не дружит он со скобками квадратными и треугольными.
ну а сам код я не проверял (уже вижу лажи), но в принципе такой
знакомо. если больше двух строк (т.е. для ламбды не годится : ), лучше записать код в файл и прицепить к сообщению. да, не видно, нужно клацнуть на причеп, но зато код сохранится, и форматирование...
ИМХО, лямбды - суть те же nested функции, только они почему-то поддерживаются далеко не во всех компилерах и не вошли в стандарт, но код с нестед функциями читается на порядок проще, чем с лямбдой. Основная идея - еще одна дополнительная иерархичность пространства имен. По идее, если имена написаны строго по какому-то канону, ни лямбды, ни nested не нужны, но ведь всегда всем лениво думать, поэтому без них сейчас сложно.
Привести пример с лямбдой не могу, так как считаю, что все можно сделать читабельнее без нее. С nested - почти также, только их иногда, грешен, пользую.
что за nested функции такие?
Это обычные функции, с телом внутри других функций или есть какие другие особенности?
Имеют ли они доступ к локальным переменным внешней функции?
Имеют ли они доступ к this (если внешняя фукция - функция класса)?
но код с нестед функциями читается на порядок проще, чем с лямбдой.
пример можно?
Кстати лямду можно присвоить локальной переменной и вызывать ее как обычную функцию.
auto fun = []() {...};
fun(); //один раз
fun(); //второй раз
Если список привязки [] оставлять пустым, то получится обычная nested функция, аргументы можно в () передать.
> Это обычные функции, с телом внутри других функций или есть какие другие особенности?
да, это GNUтое расширение, появившееся еще в конце 90х, кажется студия их категорически до сих пор не поддерживает
> Имеют ли они доступ к локальным переменным внешней функции?
да, к тем, которые определены до описания этой нестед функции
> пример можно?
void f(double *x, double *y, int K)
{ int N, M;
voiid nested(double A[M][K])
{ // переменная N видна, но L уже нет
... A[j]...
}
int L;
...
nested_ptr=nested; // не определено, если будет передано назад и вызвано после окончания работы f, но должно работать, если вызвали пока управление еще не
вернулось из f
nested(x);
...
}
в данном случае я вижу реальную пользу от этой нестед функции в том, что она маппит кусок памяти из x в виде двухмерного массива A[][] и использует его по назначению, код становится компактным и хорошо читаемым, а производительность не падает приближаясь к тому, что могло быть, если бы код был бы написан, например, на фортране.