Что такое лямбда и почему она полезна? [закрыто]


56

До сих пор я слышал о:

  • Лямбда-исчисление
  • Лямбда-программирование
  • Лямбда-выражения
  • Лямбда-функции

Что, похоже, связано с функциональным программированием ...

По всей видимости, он будет интегрирован в C ++ 1x, поэтому я мог бы лучше понять это сейчас:

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

Может кто-нибудь кратко определить, что такое лямбда-вещи, и указать, где это может быть полезно?


2
Обратите внимание, что терминология исторически возникла из желания найти хороший способ рассказать о функции, представленной выражением. Затем функция, представленная x + 1, записывается как лямбда x. х + 1.
Кастерма

В лямбда-режиме, функция ест другую функцию и / или входное значение, производит другую функцию. Это продолжается до тех пор, пока функция не найдет решение. Также яйца аллигатора .
SD

Это для меня китайская грамота. Я думаю, я пойду гироскоп, я люблю ягненка, да.

Ответы:


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

Лямбда-исчисление - это вычислительная модель, изобретенная Алонзо Черчем в 30-х годах. Синтаксис и семантика большинства функциональных языков программирования прямо или косвенно основаны на лямбда-исчислении.

Лямбда-исчисление в своей основной форме имеет две операции: абстракция (создание (анонимной) функции) и приложение (применение функции). Абстракция выполняется с помощью оператора λ, дающего имя лямбда-исчислению.

  • Лямбда-выражения
  • Лямбда-функции

Анонимные функции часто называют «лямбда-выражениями», «лямбда-функциями» или «лямбда-выражениями», потому что, как я уже говорил выше, λ был символом для создания анонимных функций в лямбда-исчислении (а слово lambdaиспользуется для создания анонимных функций во многих lisp). на основе языков по той же причине).

  • Лямбда-программирование

Это не часто используемый термин, но я предполагаю, что это означает программирование с использованием анонимных функций или программирование с использованием функций более высокого порядка.


Немного больше информации о лямбдах в C ++ 0x, их мотивации и о том, как они связаны с указателями на функции (вероятно, многое из этого повторяет то, что вы уже знаете, но я надеюсь, что это поможет объяснить мотивацию лямбд и то, как они отличаются из указателей функций):

Указатели на функции, которые уже существовали в C, весьма полезны, например, для передачи функции сравнения в функцию сортировки. Однако есть пределы их полезности:

Например, если вы хотите отсортировать вектор векторов по iэлементу th каждого вектора (где iэто параметр времени выполнения), вы не можете решить это с помощью указателя на функцию. Функция, которая сравнивает два вектора по их ith-элементу, должна принимать три аргумента ( iи два вектора), но для функции сортировки потребуется функция, принимающая два аргумента. Нам нужен способ как-то предоставить аргумент iфункции перед передачей в функцию сортировки, но мы не можем сделать это с простыми функциями Си.

Чтобы решить эту проблему, C ++ ввел понятие «функциональные объекты» или «функторы». Функтор - это в основном объект, у которого есть operator()метод. Теперь мы можем определить класс CompareByIthElement, который принимает аргумент iв качестве аргумента конструктора, а затем принимает два вектора для сравнения в качестве аргументов operator()метода. Чтобы отсортировать вектор векторов по ith-му элементу, мы можем теперь создать CompareByIthElementобъект с iаргументом и затем передать этот объект в функцию сортировки.

Поскольку функциональные объекты являются просто объектами, а не технически функциями (даже если они должны вести себя как они), вы не можете сделать указатель на функцию указателем на функциональный объект (вы, конечно, можете иметь указатель на функциональный объект, но это будет иметь тип как CompareByIthElement*и, следовательно, не будет указателем на функцию).

Большинство функций в стандартной библиотеке C ++, которые принимают функции в качестве аргументов, определяются с помощью шаблонов, чтобы они работали как с указателями на функции, так и с объектами функций.

Теперь к лямбдам:

Определение целого класса для сравнения по iэлементу th немного многословно, если вы собираетесь использовать его только один раз для сортировки вектора. Даже в том случае, когда вам нужен только указатель на функцию, определение именованной функции является субоптимальным, если она используется только один раз, потому что а) она загрязняет пространство имен и б) функция обычно будет очень маленькой и на самом деле хорошая причина абстрагировать логику в ее собственную функцию (кроме того, что вы не можете иметь указатели на функции без определения функции).

Таким образом, чтобы исправить это лямбды были введены. Лямбды - это функциональные объекты, а не указатели на функции. Если вы используете лямбда-литерал [x1, x2](y1,y2){bla}, создается код, который в основном делает следующее:

  1. Определите класс, который имеет две переменные-члены ( x1и x2) и a operator()с аргументами ( y1и y2) и телом bla.
  2. Создайте экземпляр класса, установив переменные-члены x1и x2значения переменных x1и в x2настоящее время в области видимости.

Таким образом, лямбды ведут себя как объекты функций, за исключением того, что вы не можете получить доступ к классу, который сгенерирован для реализации лямбды, кроме как с использованием лямбды. Следовательно, любая функция, которая принимает функторы в качестве аргументов (в основном это означает любую не-C-функцию в стандартной библиотеке), будет принимать лямбда-выражения, но любая функция, принимающая только указатели на функции, не будет.


Можно ли использовать анонимные функции с указателями на функции? Если нет, то в чем разница?
Jokoon

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

поэтому указатель на функцию не может содержать лямбду ...
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.