Одно из лучших объяснений lambda expression
дано автором C ++ Bjarne Stroustrup в его книге ***The C++ Programming Language***
глава 11 ( ISBN-13: 978-0321563842 ):
What is a lambda expression?
A лямбда-выражение , иногда также называемое функцией лямбда или (строго говоря, но разговорно) как лямбда , является упрощенным обозначением для определения и использования анонимного функционального объекта. Вместо определения именованного класса с помощью оператора (), позже создающего объект этого класса и, наконец, вызывающего его, мы можем использовать сокращенное обозначение.
blockquote>
When would I use one?
Это особенно полезно, когда мы хотим передать операцию в качестве аргумента алгоритму. В контексте графических пользовательских интерфейсов (и в других местах) такие операции часто называют обратными вызовами .
blockquote>
What class of problem do they solve that wasn't possible prior to their introduction?
Здесь Я предполагаю, что каждое действие, выполняемое с помощью лямбда-выражения, может быть разрешено без них, но с гораздо большим количеством кода и гораздо большей сложностью. Лямбда-выражение - это способ оптимизации вашего кода и способ сделать его более привлекательным. Как печально Stroustup:
эффективные способы оптимизации
blockquote>
Some examples
через lambda выражение
void print_modulo(const vector
& v, ostream& os, int m) // output v[i] to os if v[i]%m==0 { for_each(begin(v),end(v), [&os,m](int x) { if (x%m==0) os << x << '\n'; }); } или через функцию
class Modulo_print { ostream& os; // members to hold the capture list int m; public: Modulo_print(ostream& s, int mm) :os(s), m(mm) {} void operator()(int x) const { if (x%m==0) os << x << '\n'; } };
или даже
void print_modulo(const vector
& v, ostream& os, int m) // output v[i] to os if v[i]%m==0 { class Modulo_print { ostream& os; // members to hold the capture list int m; public: Modulo_print (ostream& s, int mm) :os(s), m(mm) {} void operator()(int x) const { if (x%m==0) os << x << '\n'; } }; for_each(begin(v),end(v),Modulo_print{os,m}); } , если вам нужно u, можно назвать
lambda expression
, как показано ниже:void print_modulo(const vector
& v, ostream& os, int m) // output v[i] to os if v[i]%m==0 { auto Modulo_print = [&os,m] (int x) { if (x%m==0) os << x << '\n'; }; for_each(begin(v),end(v),Modulo_print); } Или предположим, что еще один простой образец
void TestFunctions::simpleLambda() { bool sensitive = true; std::vector
v = std::vector ({1,33,3,4,5,6,7}); sort(v.begin(),v.end(), [sensitive](int x, int y) { printf("\n%i\n", x < y); return sensitive ? x < y : abs(x) < abs(y); }); printf("sorted"); for_each(v.begin(), v.end(), [](int x) { printf("x - %i;", x); } ); } будет генерировать следующий
0
1
0
1
0
1
0
1
0
1
0 sortedx - 1; x - 3; x - 4; x - 5; x - 6; x - 7; x - 33;
blockquote>
[]
- это список захвата илиlambda introducer
: еслиlambdas
не требует доступа к своей локальной среде, мы можем его использовать.Цитата из книги:
Первая Характер лямбда-выражения всегда [. Интенсификатор лямбда может принимать различные формы:
• []: пустой список захвата. Это означает, что никакие локальные имена из окружающего контекста не могут использоваться в лямбда-теле. Для таких лямбда-выражений данные получены из аргументов или из нелокальных переменных.
• [& amp;]: неявно захватывать по ссылке. Можно использовать все локальные имена. Доступ ко всем локальным переменным осуществляется по ссылке.
• [=]: неявно фиксировать по значению. Можно использовать все локальные имена. Все имена относятся к копиям локальных переменных, взятых в точке вызова лямбда-выражения.
• [capture-list]: явный захват; Список захвата - это список имен локальных переменных, которые должны быть захвачены (т. е. сохранены в объекте) по ссылке или по значению. Переменные с именами, которым предшествует & amp; записываются по ссылке. Другие переменные фиксируются по значению. Список захвата также может содержать это и имена, за которыми следуют ... как элементы.
• [& amp ;, capture-list]: неявно захватывать по ссылке все локальные переменные с именами, не указанными в списке. Этот список может содержать список захвата. Перечисленным именам не может предшествовать & amp ;. Переменные, названные в списке захвата, записываются по значению.
• [=, capture-list]: неявно захватывать по значению все локальные переменные с именами, не указанными в списке. Список захвата не может содержать этого. Перечисленным именам должно предшествовать & amp ;. Вариаторы, названные в списке захвата, записываются по ссылке.
Обратите внимание, что локальное имя, которому предшествует & amp; всегда фиксируется по ссылке и локальное имя, не указанное с помощью & amp; всегда фиксируется по значению.
blockquote>
Additional
Lambda expression
formatДополнительные ссылки:
- Wiki
- open-std.org , глава 5.1.2
Совершенно определенно все вещи из Вашего списка для каждого отдельного объекта:
От вершины моей головы не очень еще, но для группы тестов я хотел бы знать
Должно быть очень, очень легко записать тест, и одинаково легкий выполнить их. Это, мне, является единственной самой важной функцией ремня безопасности тестирования. Если кто-то должен включить GUI или переход через набор обручей для записи теста, они не будут использовать его.
Произвольный набор тегов - таким образом, я могу отметить тест как, например, "интеграция, UI, администратор".
(Вы знали, что я собирался попросить это, не сделал Вас:-)
К тому, что Вы сказали, что я добавлю:
Любой вид диагностического вывода - особенно при отказе очень важен. Если тест перестал работать, Вы не хотите всегда должными быть повторно выполнять тест под отладчиком для наблюдения то, что произошло - в выводе должен быть некоторый cludes.
мне также нравится видеть прежде и после снимка критических системных переменных как память или пространство на жестком диске, доступное, поскольку те могут дать большие представления также.
Наконец, если Вы используете случайные семена для какого-либо из тестов, выписывают семя к файлу журнала так, чтобы тест мог быть воспроизведен при необходимости.
Я хотел бы способность связать и вложить потоки TAP.
Уникальный идентификатор (uuid, md5sum), чтобы быть в состоянии определить отдельный тест - говорят, для использования при вставке результатов испытаний в базу данных или идентификации их в средстве отслеживания ошибки, чтобы позволить QA повторно выполнить отдельный тест.
Это также позволило бы проследить поведение отдельного теста от от сборки к сборке до всего жизненного цикла нескольких изменений продукта. Это могло в конечном счете позволить корреляции более широкого масштаба между 'историческими' событиями (новый наем, версия продукта, модернизация оборудования) и профиль (профили) тестов, которые перестали работать в результате таких событий.
я также думаю, что TAP должен быть испущен через выделенный канал стороны, а не смешан в с stdout. Я не уверен, что это находится под объемом определения протокола.
Я использую TAP в качестве выходного протокола для ряда простых методов тестирования C++ и видел следующие недостатки:
В конце, тестовый вывод должен подойти как основание для того, чтобы легко генерировать файл отчета HTML, который перечисляет тесты, за которыми следуют, очень кратко, дает подробный вывод для проваленных тестов и позволяет быстро вскочить в IDE к провальной тестовой строке.
необязательный вывод в цвете ascii, зеленый для хорошего, желтый для ожидающих, красный для ошибок
идея о том, что что-то ожидает
сводка в конце отчета о тестировании команд, которые будет запускать отдельные тесты, где
элемент списка
что-то пошло не так
что-то в тесте ожидалось