Що таке лямбда, і чому це було б корисно? [зачинено]


56

Поки я чув про:

  • Обчислення лямбда
  • Програмування лямбда
  • Лямбда-вирази
  • Функції лямбда

Яке все, здається, пов'язане з функціональним програмуванням ...

Мабуть, вона буде інтегрована в C ++ 1x, тому я можу краще зрозуміти це зараз:

http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions

Чи може хтось коротко визначити, що таке речі лямбда, і дати там, де це може бути корисно?


2
Зауважте, що термінологія історично походить від того, щоб бажати хорошого способу говорити про функцію, представлену виразом. Потім функція, представлена ​​x + 1, записується лямбда x. х + 1.
кастерма

Ламбда-способом функція їсть іншу функцію та / або вхідне значення, виробляє іншу функцію. Це триває, поки функція не виробляє рішення. Також яйця алігатора .
СД

Це все грецьке для мене. Думаю, я піду в гіроскоп, мені подобається баранина, да.

Відповіді:


44
  • Обчислення лямбда

Обчислення лямбда - це обчислювальна модель, винайдена Церквою Алонцо в 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}код, генерується код, який в основному робить наступне:

  1. Визначте клас, який має дві змінні ( x1та x2) та an operator()з аргументами ( y1і y2) та тілом bla.
  2. Створити екземпляр класу, встановлюючи змінні - члени x1і x2до значень змінних x1і в x2даний час в області.

Отже, лямбда поводяться як об'єкти функцій, за винятком того, що ви не можете отримати доступ до класу, який створений для реалізації лямбда будь-яким іншим способом, ніж використання лямбда. Отже, будь-яка функція, яка приймає функтори як аргументи (в основному маючи на увазі будь-яку не-C функцію в стандартній бібліотеці), буде приймати лямбда, але будь-яка функція, яка приймає лише покажчики функцій, не буде.


Чи використовуються анонімні функції з покажчиками функцій? Якщо ні, в чому різниця?
jokoon

1
@jokoon: Ні, анонімні функції не можна передавати як параметри функціям, які приймають лише покажчики функцій. Однак більшість функцій, які приймають функції як аргументи, визначені за допомогою шаблонів, щоб вони могли приймати будь-який об’єкт функції як аргумент, а не лише покажчик функції. Тобто в більшості місць, де ви можете використовувати функціональні вказівники ( std::sortнаприклад), ви зможете замість цього використовувати анонімні функції. Однак, визначаючи функцію, яка повинна брати анонімну функцію в якості аргументу, потрібно або використовувати шаблон, або використовувати std::functionяк тип аргументу.
sepp2k

тому вказівник функції не може містити лямбда ...
jokoon

1
+1 Відмінне пояснення - я також не зміг цього дізнатися.
Майкл К

2
Я з Майклом на цьому. Це дуже всебічно. +1від мене.
sbi

18

В основному, лямбда-функції - це функції, які ви створюєте "на льоту". У C ++ 1x їх можна використовувати для покращення його підтримки функціонального програмування:

std::for_each( begin, end, [](int i){std::cout << i << '\n';} );

Це приблизно призведе до коду, подібного до цього:

struct some_functor {
  void operator()(int i) {std::cout << i << '\n';}
};

std::for_each( begin, end, some_functor() );

Якщо вам потрібно some_functorлише для цього одного дзвінка std::for_each(), то ця лямбда-функція має кілька переваг перед цим:

  • те, що робиться в циклі, задається прямо там, де викликається циклічна функція
  • це позбавляє вас від написання деяких кодів плит котла
  • не існує жодного функтора, який лежить навколо деякої області простору імен, яка змушує всіх, хто дивиться на код, цікавитись для чого він потрібен

7

Функція лямбда - це інша назва анонімної функції - по суті це функція без імені.

Зазвичай ви використовуєте це мовами, де вам потрібно буде використовувати функцію лише один раз. Наприклад замість

def add(a, b)
  return a+b

а потім передати цю функцію в іншу функцію на зразок такої

reduce(add, [5,3,2])

З лямбда ви просто зробили б

reduce(lambda x, y: a+b, [5,3,2])
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.