Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

лямда в c11 польза или извращение?

404  1 2 все
-sh- завсегдатай08.12.17 16:58
08.12.17 16:58 
Последний раз изменено 08.12.17 17:03 (-sh-)

я обычно лямды применяю с STL, там где раньше (до С11) предикаты применял.

Но вот обнаружил еще вариант:

void fun()

{

...

...

...[&]() // лямда функция

...{

... ...

...}();

....

}

там где точки может быть куча другого кода.

Как минимум одно оправдание такому коду я придумал - чтобы одним нажатием F10 (в ВизуалСтудии) весь код что в лямде перепрыгнуть. А может еще есть?

#1 
AlexNek патриот08.12.17 21:44
AlexNek
NEW 08.12.17 21:44 
в ответ -sh- 08.12.17 16:58

Это во всех языках - религия. Кому то нравится, кому то нет.

http://archive.kalnytskyi.com/2011/10/30/introduction-to-c...

https://habrahabr.ru/post/66021/

#2 
  moose старожил09.12.17 16:30
NEW 09.12.17 16:30 
в ответ -sh- 08.12.17 16:58, Последний раз изменено 09.12.17 16:31 (moose)

в c# это изначально присутствует, пользуюсь иногда. когда нужно проделать что-то один раз, и хочется, чтобы было сразу тут, на месте видно, что именно проделывается, а не нужно лезть куда-то еще, чтобы посмотреть, что конкретно делает ф-я. при использовании linq иногда просто не знаю, как бы без ламбды обходиться. привыкнуть к форме записи нужно просто, тогда вопросы "зачем" не будут возникать. к макро в си привыкнуть вообще невозможно: привыкать нужно к каждой индивидуально и на каждую нужно лезь и смотреть, что она там выделывает, и не всегда правильно поймешь : )

#3 
dymanoid знакомое лицо09.12.17 23:14
dymanoid
NEW 09.12.17 23:14 
в ответ -sh- 08.12.17 16:58

Основное преимущество лямбды - это возможность захвата (capture) переменных. Некоторые вещи без лямбды невозможно реализовать в принципе (без кривых костылей).

#4 
  moose старожил09.12.17 23:28
NEW 09.12.17 23:28 
в ответ dymanoid 09.12.17 23:14

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

#5 
dymanoid знакомое лицо11.12.17 21:13
dymanoid
NEW 11.12.17 21:13 
в ответ moose 09.12.17 23:28

Классический пример - использование std::алгоритмов. Например, вам надо отсортировать вектор векторов по i-му элементу этих векторов, причём i задаётся во время выполнения. Алгоритм сортировки принимает два параметра, но нам надо передать три. Классическое решение с костылями - пишем функтор с конструктором, принимающим i как параметр, далее по схеме. Недостатки очевидны - функтор надо писать и мейнтейнить, во время дизайна определять, что передавать в конструктор и т.п. Типичный костыль в вакууме. Много кода, выхлопа мало. Лямбда решает все проблемы с помощью захвата контекста (по желанию автоматического) прямо при вызове алгоритма.

#6 
  moose старожил11.12.17 23:19
NEW 11.12.17 23:19 
в ответ dymanoid 11.12.17 21:13

можете привести реальный РАБОТАЮЩИЙ код "с костылями" и без? для std::vector<std::vector<int> >

как туда втулить это i? чтобы было попроще и понагляднее.

#7 
dymanoid знакомое лицо12.12.17 00:26
dymanoid
NEW 12.12.17 00:26 
в ответ moose 11.12.17 23:19

Мне лень. На словах я объяснил, за деталями - добро пожаловать на stackoverflow.

#8 
  moose старожил12.12.17 10:33
NEW 12.12.17 10:33 
в ответ dymanoid 12.12.17 00:26

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

#9 
dymanoid знакомое лицо12.12.17 19:05
dymanoid
NEW 12.12.17 19:05 
в ответ moose 12.12.17 10:33

Ваша способность делать выводы потрясающая. За сим откланиваюсь.

#10 
  moose старожил12.12.17 19:27
NEW 12.12.17 19:27 
в ответ dymanoid 12.12.17 19:05, Последний раз изменено 12.12.17 23:33 (moose)

жаль, что вы решили стать в позу вместо потратить пять минут и привести пример кода (уже имеющегося, я так понимаю). послать на stackoverflow и отшаркаться - это проще всего, и не придает вашему мнению веса.

#11 
Программист коренной житель13.12.17 08:55
NEW 13.12.17 08:55 
в ответ dymanoid 11.12.17 21:13
Классическое решение с костылями - пишем функтор с конструктором, принимающим i как параметр, далее по схеме. Недостатки очевидны - функтор надо писать и мейнтейнить, во время дизайна определять, что передавать в конструктор и т.п. Типичный костыль в вакууме. Много кода, выхлопа мало. Лямбда решает все проблемы с помощью захвата контекста (по желанию автоматического) прямо при вызове алгоритма.

Вопрос спорный.

Во-первых, лямбда нетестируема сама по себе. Т.е. если у тебя цикломатическая сложность лямбды больше 1, то привет.

Во-вторых, лямбда совершенно негибкая конструкция. Т.е. если у тебя в одном случае вектор векторов, а в другом вектор словарей, то придется тебе писать код два раза, вместо того, чтобы передать вектор + нужный функтор.

Во-третьих, если у тебя есть несколько мест с похожей сортировкой, то придется тебе лямбду дублировать.


#12 
anly коренной житель15.12.17 18:58
anly
NEW 15.12.17 18:58 
в ответ Программист 13.12.17 08:55
Во-третьих, если у тебя есть несколько мест с похожей сортировкой, то придется тебе лямбду дублировать.
я так понимаю, что если появилась нужда лямду дублировать, то нужно лямду обозвать как следует - т.е. сделать из нее нормальную функцию. НО! только если функция не чуть сложнее примитивной. Примитивные вещи можно даже в лямдах дублировать.

Да и вообще, на мой взгляд, удел лямд - чтото простенькое и маленькое.

Проклят нарушающий межи ближнего своего (Втор.27:17)
#13 
anly коренной житель15.12.17 19:14
anly
NEW 15.12.17 19:14 
в ответ moose 11.12.17 23:19, Последний раз изменено 15.12.17 19:27 (anly)

с костылями:

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>;} );


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

Проклят нарушающий межи ближнего своего (Втор.27:17)
#14 
anly коренной житель15.12.17 19:29
anly
NEW 15.12.17 19:29 
в ответ anly 15.12.17 19:14, Последний раз изменено 15.12.17 19:32 (anly)

при попытке редактировать сайт вообще половину текста выбрасывает! Не дружит он со скобками квадратными и треугольными.

ну а сам код я не проверял (уже вижу лажи), но в принципе такой

Проклят нарушающий межи ближнего своего (Втор.27:17)
#15 
  moose старожил15.12.17 20:34
NEW 15.12.17 20:34 
в ответ anly 15.12.17 19:14

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

#16 
  ilghiz постоялец15.12.17 21:44
NEW 15.12.17 21:44 
в ответ -sh- 08.12.17 16:58

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


Привести пример с лямбдой не могу, так как считаю, что все можно сделать читабельнее без нее. С nested - почти также, только их иногда, грешен, пользую.

#17 
anly коренной житель16.12.17 10:19
anly
NEW 16.12.17 10:19 
в ответ ilghiz 15.12.17 21:44, Последний раз изменено 16.12.17 10:35 (anly)

что за nested функции такие?

Это обычные функции, с телом внутри других функций или есть какие другие особенности?

Имеют ли они доступ к локальным переменным внешней функции?

Имеют ли они доступ к this (если внешняя фукция - функция класса)?

но код с нестед функциями читается на порядок проще, чем с лямбдой.

пример можно?


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

auto fun = []() {...};

fun(); //один раз

fun(); //второй раз


Если список привязки [] оставлять пустым, то получится обычная nested функция, аргументы можно в () передать.

Проклят нарушающий межи ближнего своего (Втор.27:17)
#18 
  ilghiz постоялец16.12.17 15:45
NEW 16.12.17 15:45 
в ответ anly 16.12.17 10:19, Последний раз изменено 16.12.17 17:44 (ilghiz)

> Это обычные функции, с телом внутри других функций или есть какие другие особенности?

да, это 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[][] и использует его по назначению, код становится компактным и хорошо читаемым, а производительность не падает приближаясь к тому, что могло быть, если бы код был бы написан, например, на фортране.

#19 
Murr патриот16.12.17 17:19
Murr
NEW 16.12.17 17:19 
в ответ ilghiz 16.12.17 15:45

к тем, которые определены до описания этой нестед функции

------

Жутики, имхо...

#20 
1 2 все