====== В двух словах ====== Boost Lambda Library (далее BLL) - библиотека шаблонов C++, которая имплементирует форму lambda-абстракций (//lambda abstractions//) для C++. Термин происходит из функционального программирования и lambda-вычислений, где lambda-абстракция определяет безымянную функцию (//unnamed function//). Первичная мотивировка для BLL – обеспечить гибкий, и удобный способ определения безымянных функциональных объектов для алгоритмов STL. В объяснении, чем является библиотека, строка кода говорит больше чем тысяча слов; следующая строка выводит разделенные пробелами элементы некоторого контейнера: for_each (a.begin (), a.end (), std::cout<<_1<<''); Выражение std:: cout <<_1 <<' ' определяет одиночный функциональный объект. Переменная _1 –параметр этой функции, метка-заполнитель (//placeholder//) для фактического параметра. В пределах каждой итерации for_each, функция вызывается с элементом **a** в качестве фактического параметра. Этот фактический параметр подставляется вместо //placeholder//, и определяется "тело" функции. Сущность BLL позволяет Вам определять маленькие безымянные функциональные объекты, такие как предыдущий, непосредственно в месте вызова алгоритма STL. ====== Введение ====== ===== Обоснование ===== Стандартная Библиотека Шаблонов (STL) [ [[ http://www.boost.org/doc/html/lambda.html#cit:stepanov:94 | STL94]]], теперь часть Стандартной Библиотеки C++ [ [[http://www.boost.org/doc/html/lambda.html#cit:c++:98 | C++98]]], является основной библиотекой контейнеров и алгоритмов. Обычно алгоритмы STL выполняют операции над элементами контейнера через функторы. Эти функторы передаются алгоритмам в качестве аргументов. Любая конструкция C++, которая может быть вызвана с синтаксисом вызова функции, - функтор. STL содержит предопределенные функторы для некоторых общих операторов (типа 'плюс','меньше' и 'not 1'). Как пример, возможное имплементирование для шаблона стандартного плюса: template struct plus : public binary_function{ T operator()(const T& i, const T& j) const { return i + j; } }; Базовый класс binary_function содержит typedefs для параметров и возвращаемых типов функтора, которые необходимы, чтобы сделать функциональный объект адаптируемым. В дополнение к основным функторам классов, таких как указаны выше, STL содержит шаблоны связывания (//binder templates//) для создания унарного функтора из адаптируемого бинарного функтора, фиксированием одного из параметров константным значением. Например, вместо имеющегося, явно написать функтор как: class plus_1 { int _i; public: plus_1(const int& i) : _i(i) {} int operator()(const int& j) { return _i + j; } }; эквивалентная функциональность может быть достигнута с шаблоном plus и одним из шаблонов связывания(//bind1st//). Например, следующие два выражения создают функторы с идентичными функциональными возможностями; когда вызваются, оба возвращают результат добавления 1 к аргументу функтора: plus_1(1) bind1st(plus(), 1) Подвыражение plus() в последней строке - бинарный функтор, который вычисляет сумму двух целых чисел, и bind1st вызывает этот функтор, частично привязав первый аргумент к 1. В качестве примера использования вышеупомянутого функтора, следующий код добавляет 1 к каждому элементу некоторого контейнера **a** и выводит результаты в поток стандартного вывода cout. transform(a.begin(),a.end(),ostream_iterator(cout),bind1st(plus(),1)); Чтобы сделать шаблоны связывания более широко применимыми, STL содержит адаптеры для выполнения указателей или ссылок на функции и указателей на функции-члены, адаптируемыми. Наконец, некоторые реализации STL содержат функциональные составные операции, как расширения Стандарта [ [[http://www.boost.org/doc/html/lambda.html#cit:sgi:02 | SGI02]]]. Все эти средства стремятся к одной цели: позволить определить безымянные функции в вызове алгоритма STL, другими словами, передавать фрагменты кода в качестве параметра функции. Однако, эта цель достигнута только частично. Простой пример выше показывает, что определение безымянных функций стандартными средствами является громоздким. Сложные выражения, задействующие функторы, адаптеры, биндеры(//binders//) и функциональные составные операции трудны для понимания. В дополнение к этому, есть существенные ограничения в применении стандартных средств. Например, стандартные биндеры позволяют связать только один аргумент бинарной функции; нет никаких биндеров для 3-х, 4-х и т.д. функций. Boost Lambda Library обеспечивает решения, описанных выше проблем: * Безымянные функции могут быть созданы легко и с интуитивно-понятным синтаксисом. Вышеупомянутый пример может быть записан как: transform(a.begin(), a.end(), ostream_iterator(cout), 1 + _1); или ещё более понятно: for_each(a.begin(), a.end(), cout << (1 + _1)); * Удалено большинство ограничений для аргументов связывания, могут быть связаны произвольные параметры фактически любой функции C++ . * Нет необходимости в разделении функциональных составных операций, поскольку функциональная композиция поддерживается неявно. ===== Введение в lambda-выражения ===== Lambda-выражения обычны для функциональных языков программирования. Их синтаксис варьируется между языками (и между различными формами lambda-исчислений), но каноническая форма lambda-выражений такова: lambda x1...xn.e Lambda-выражение определяет безымянную функцию и состоит из: * параметров этой функции: x1...xn. * выражения e, которое вычисляет значение функции в границах x1...xn. Простой пример lambda-выражения: lambda x y.x+y Применение lambda-функции означает замену формальных параметров фактическими: (lambda x y.x+y) 2 3 = 2 + 3 = 5 В версии lambda-выражений для C++ часть lambda x1...xn, и формальные параметры имеют предопределенные названия. В текущей версии библиотеки, есть три таких предопределенных формальных параметра, названные метками-заполнителями: _1, _2 и _3. Они обращаются к первому, второму и третьему параметру функции, определенной lambda-выражением. Например, в C++ версия определения lambda x y.x+y это _1 + _2 Следовательно, нет никакого синтаксического ключевого слова для lambda-выражений в C++. Использование метки-заполнителя как операнда подразумевает, что вызов оператора - lambda-выражение. Однако, это истинно только для вызовов оператора. Выражения лямбды, содержащие вызовы функций, управляющие структуры, приведения и т.д. требуют специальных синтаксических конструкций. Что наиболее важно, функциональные вызовы должны быть обернуты в bind-функции. Как пример, рассмотрим lambda-выражение: lambda x y.foo(x,y) вовсе не foo(_1, _2), C++-копия этого выражения: bind(foo, _1, _2) Обращаем Ваше внимание на этот тип lambda-выражений C++, как bind-выражений. Lambda-выражение определяет функтор C++, следовательно синтаксис функциональных приложений походит на вызов любого другого функтора, например: (_1 + _2)(i, j). Полную документацию и примеры использования можно найти в оригинальной документации: http://www.boost.org/doc/html/lambda.html