Лямбда-исчисление - это вычислительная модель, изобретенная Алонзо Черчем в 30-х годах. Синтаксис и семантика большинства функциональных языков программирования прямо или косвенно основаны на лямбда-исчислении.
Лямбда-исчисление в своей основной форме имеет две операции: абстракция (создание (анонимной) функции) и приложение (применение функции). Абстракция выполняется с помощью оператора λ, дающего имя лямбда-исчислению.
- Лямбда-выражения
- Лямбда-функции
Анонимные функции часто называют «лямбда-выражениями», «лямбда-функциями» или «лямбда-выражениями», потому что, как я уже говорил выше, λ был символом для создания анонимных функций в лямбда-исчислении (а слово lambda
используется для создания анонимных функций во многих lisp). на основе языков по той же причине).
Это не часто используемый термин, но я предполагаю, что это означает программирование с использованием анонимных функций или программирование с использованием функций более высокого порядка.
Немного больше информации о лямбдах в C ++ 0x, их мотивации и о том, как они связаны с указателями на функции (вероятно, многое из этого повторяет то, что вы уже знаете, но я надеюсь, что это поможет объяснить мотивацию лямбд и то, как они отличаются из указателей функций):
Указатели на функции, которые уже существовали в C, весьма полезны, например, для передачи функции сравнения в функцию сортировки. Однако есть пределы их полезности:
Например, если вы хотите отсортировать вектор векторов по i
элементу th каждого вектора (где i
это параметр времени выполнения), вы не можете решить это с помощью указателя на функцию. Функция, которая сравнивает два вектора по их i
th-элементу, должна принимать три аргумента ( i
и два вектора), но для функции сортировки потребуется функция, принимающая два аргумента. Нам нужен способ как-то предоставить аргумент i
функции перед передачей в функцию сортировки, но мы не можем сделать это с простыми функциями Си.
Чтобы решить эту проблему, C ++ ввел понятие «функциональные объекты» или «функторы». Функтор - это в основном объект, у которого есть operator()
метод. Теперь мы можем определить класс CompareByIthElement
, который принимает аргумент i
в качестве аргумента конструктора, а затем принимает два вектора для сравнения в качестве аргументов operator()
метода. Чтобы отсортировать вектор векторов по i
th-му элементу, мы можем теперь создать CompareByIthElement
объект с i
аргументом и затем передать этот объект в функцию сортировки.
Поскольку функциональные объекты являются просто объектами, а не технически функциями (даже если они должны вести себя как они), вы не можете сделать указатель на функцию указателем на функциональный объект (вы, конечно, можете иметь указатель на функциональный объект, но это будет иметь тип как CompareByIthElement*
и, следовательно, не будет указателем на функцию).
Большинство функций в стандартной библиотеке C ++, которые принимают функции в качестве аргументов, определяются с помощью шаблонов, чтобы они работали как с указателями на функции, так и с объектами функций.
Теперь к лямбдам:
Определение целого класса для сравнения по i
элементу th немного многословно, если вы собираетесь использовать его только один раз для сортировки вектора. Даже в том случае, когда вам нужен только указатель на функцию, определение именованной функции является субоптимальным, если она используется только один раз, потому что а) она загрязняет пространство имен и б) функция обычно будет очень маленькой и на самом деле хорошая причина абстрагировать логику в ее собственную функцию (кроме того, что вы не можете иметь указатели на функции без определения функции).
Таким образом, чтобы исправить это лямбды были введены. Лямбды - это функциональные объекты, а не указатели на функции. Если вы используете лямбда-литерал [x1, x2](y1,y2){bla}
, создается код, который в основном делает следующее:
- Определите класс, который имеет две переменные-члены (
x1
и x2
) и a operator()
с аргументами ( y1
и y2
) и телом bla
.
- Создайте экземпляр класса, установив переменные-члены
x1
и x2
значения переменных x1
и в x2
настоящее время в области видимости.
Таким образом, лямбды ведут себя как объекты функций, за исключением того, что вы не можете получить доступ к классу, который сгенерирован для реализации лямбды, кроме как с использованием лямбды. Следовательно, любая функция, которая принимает функторы в качестве аргументов (в основном это означает любую не-C-функцию в стандартной библиотеке), будет принимать лямбда-выражения, но любая функция, принимающая только указатели на функции, не будет.