Обчислення лямбда - це обчислювальна модель, винайдена Церквою Алонцо в 30-х роках. Синтаксис та семантика більшості функціональних мов програмування прямо чи опосередковано надихаються на обчислення лямбда.
Обчислення лямбда у своїй найпростішій формі має дві операції: абстрагування (створення (анонімної) функції) та застосування (застосувати функцію). Абстракцію виконують за допомогою оператора λ, даючи лямбда-обчислення свою назву.
- Лямбда-вирази
- Функції лямбда
Анонімні функції часто називають "лямбда", "лямбда-функції" або "лямбда-виразами", оскільки, як я вже говорив вище, λ був символом для створення анонімних функцій в обчисленні лямбда (і це слово lambda
використовується для створення анонімних функцій у багатьох lisp -мовні мови з тієї ж причини).
Це не часто вживаний термін, але я припускаю, що це означає програмування з використанням анонімних функцій або програмування з використанням функцій вищого порядку.
Трохи більше інформації про лямбдаси в C ++ 0x, їх мотивацію та те, як вони відносяться до функціональних покажчиків (багато цього, мабуть, є повторенням того, що ви вже знаєте, але, сподіваюся, це допоможе пояснити мотивацію лямбда і як вони відрізняються з функціональних покажчиків):
Функціональні покажчики, які вже існували в С, є досить корисними, наприклад, для передачі функції порівняння функції сортування. Однак є обмеження їх корисності:
Наприклад, якщо ви хочете сортувати вектор векторів по t- i
му елементу кожного вектора (де i
параметр часу виконання), ви не можете вирішити це за допомогою функції вказівника. Функція, яка порівнює два вектори за їх- i
м елементом, повинна взяти три аргументи ( i
і два вектори), але для функції сортування потрібна функція, яка бере два аргументи. Що нам знадобиться - це спосіб якось поставити аргумент i
функції перед тим, як передати її функції сортування, але ми не можемо це зробити з простими функціями C.
Для вирішення цього питання C ++ ввів поняття "об'єкти функцій" або "функтори". Функтор в основному є об'єктом, який має operator()
метод. Тепер ми можемо визначити клас CompareByIthElement
, який бере аргумент i
як аргумент конструктора, а потім бере два вектори для порівняння як аргументи operator()
методу. Щоб сортувати вектор векторів по i
елементу th, тепер ми можемо створити CompareByIthElement
об'єкт з i
аргументом, а потім передати цей об’єкт функції сортування.
Оскільки об'єкти функцій - це лише об'єкти, а не технічно функції (навіть якщо вони призначені для того, щоб вони поводилися як вони), ви не можете зробити покажчик функції на об'єкт функції (ви, звичайно, можете мати вказівник на функціональний об'єкт, але це мав би тип типу CompareByIthElement*
і, таким чином, не був би покажчиком функції).
Більшість функцій у стандартній бібліотеці C ++, які приймають функції як аргументи, визначаються за допомогою шаблонів, щоб вони працювали як з покажчиками функцій, так і з об'єктами функцій.
Тепер лямбдам:
Визначення цілого класу для порівняння за i
елементом th є дещо багатослівним, якщо ви збираєтесь використовувати його лише один раз для сортування вектора. Навіть у випадку, коли вам потрібен лише покажчик функції, визначення іменованої функції є неоптимальним, якщо вона використовується лише один раз, оскільки а) вона забруднює простір імен і б) функція зазвичай буде дуже маленькою і насправді насправді немає вагомий привід абстрагувати логіку у власній функції (крім того, що ви не можете мати покажчики функцій, не визначаючи функцію).
Тож для виправлення цього лямбда були введені. Лямбди - це функціональні об'єкти, а не функціональні покажчики. Якщо ви використовуєте лямбда-буквальний [x1, x2](y1,y2){bla}
код, генерується код, який в основному робить наступне:
- Визначте клас, який має дві змінні (
x1
та x2
) та an operator()
з аргументами ( y1
і y2
) та тілом bla
.
- Створити екземпляр класу, встановлюючи змінні - члени
x1
і x2
до значень змінних x1
і в x2
даний час в області.
Отже, лямбда поводяться як об'єкти функцій, за винятком того, що ви не можете отримати доступ до класу, який створений для реалізації лямбда будь-яким іншим способом, ніж використання лямбда. Отже, будь-яка функція, яка приймає функтори як аргументи (в основному маючи на увазі будь-яку не-C функцію в стандартній бібліотеці), буде приймати лямбда, але будь-яка функція, яка приймає лише покажчики функцій, не буде.