什么是lambda,为什么有用?[关闭]


56

到目前为止,我听说:

  • λ演算
  • Lambda程式设计
  • Lambda表达式
  • Lambda函数

这似乎都与函数式编程有关...

显然它将被集成到C ++ 1x中,所以我现在可能会更好地理解它:

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

有人可以简短地定义什么是lambda事物,并给出一个有用的地方吗?


2
请注意,该术语在历史上源于想要一种好的方法来讨论表达式所表示的功能。然后将x + 1表示的函数写为lambda x。x + 1。
kasterma 2010年

以lambda方式,一个函数吃另一个函数和/或一个输入值,产生另一个函数。这一直持续到函数产生解决方案为止。另外,鳄鱼皮蛋
SD

对我来说全是希腊文。我想我要去玩陀螺仪,我喜欢羊羔,du。

Answers:


44
  • λ演算

λ演算是30年代Alonzo Church发明的一种计算模型。大多数功能性编程语言的语法和语义直接或间接地受到lambda演算的启发。

最基本形式的lambda演算有两个操作:抽象(创建(匿名)函数)和应用(应用函数)。使用λ运算符执行抽象,为lambda微积分取名。

  • Lambda表达式
  • Lambda函数

匿名函数通常被称为“ lambdas”,“ lambda函数”或“ lambda表达式”,因为如上所述,λ是在lambda演算中创建匿名函数的符号(该词lambda在许多lisp中用于创建匿名函数基于相同语言的语言)。

  • Lambda程式设计

这不是一个常用术语,但是我认为这意味着使用匿名函数进行编程或使用高阶函数进行编程。


有关C ++ 0x中的lambda,它们的动机以及它们与函数指针的关系的更多信息(很多可能是您已经知道的重复,但是我希望它可以帮助解释lambda的动机以及它们之间的区别从函数指针):

函数指针(已存在于C中)对于例如将比较函数传递给排序函数非常有用。但是,它们的用途受到限制:

例如,如果要按i每个向量的第th个元素对向量进行排序(其中i是运行时参数),则无法使用函数指针来解决。一个将两个向量按其ith元素进行比较的函数将需要使用三个参数(i以及两个向量),但是sorting函数将需要一个使用两个参数的函数。我们需要的是一种在将参数i传递给排序函数之前以某种方式将其提供给函数的方法,但是我们不能使用普通的C函数来做到这一点。

为了解决这个问题,C ++引入了“功能对象”或“功能部件”的概念。函子基本上是具有operator()方法的对象。现在,我们可以定义一个类CompareByIthElement,该类将参数i作为构造函数参数,然后将要比较的两个向量作为operator()方法的参数。为了通过ith元素对向量进行排序,我们现在可以创建一个CompareByIthElement对象i作为参数,然后将该对象传递给排序函数。

由于函数对象只是对象,从技术上来说并不是函数(即使它们的行为与它们相同),因此不能使函数指针指向函数对象(当然可以具有指向函数对象的指针,但是它可以将具有类似的类型CompareByIthElement*,因此不是函数指针)。

C ++标准库中大多数以函数为参数的函数都是使用模板定义的,因此它们可以与函数指针以及函数对象一起使用。

现在到lambdas:

i如果只用一次它来对向量进行排序,那么用th元素定义要比较的整个类会有点冗长。即使在只需要一个函数指针的情况下,如果仅使用一次,则定义命名函数也是次优的,因为a)它会污染名称空间,b)该函数通常会非常小,并且实际上并没有将逻辑抽象为自己的函数的一个很好的理由(除了没有定义函数就不能拥有函数指针的原因)。

因此,为了解决此问题,引入了lambda。Lambda是函数对象,而不是函数指针。如果使用lambda文字,[x1, x2](y1,y2){bla}则会生成类似代码的代码,该代码基本上会执行以下操作:

  1. 定义一个类,该类具有两个成员变量(x1x2),一个operator()具有参数(y1y2)和主体bla
  2. 创建类的实例,成员变量x1x2对变量的值x1x2当前在范围之内。

因此,lambda的行为类似于函数对象,但除了使用lambda之外,您无法以其他任何方式访问为实现lambda而生成的类。因此,任何接受函子作为参数的函数(基本上意味着标准库中的任何非C函数)都将接受lambda,但仅接受函数指针的任何函数均不会接受。


匿名函数是否与函数指针一起使用?如果不是,有什么区别?
jokoon 2010年

1
@jokoon:不,匿名函数不能作为参数传递给仅采用函数指针的函数。但是,大多数将函数作为参数的函数都是使用模板定义的,因此它们可以将任何类型的函数对象作为参数,而不仅仅是函数指针。也就是说,在大多数可以使用函数指针的地方(std::sort例如),您将能够使用匿名函数。但是,在定义应将匿名函数作为其参数的函数时,您需要使用模板或将其std::function用作参数的类型。
sepp2k 2010年

因此函数指针不能包含lambda ...
jokoon 2010年

1
+1出色的解释-我也无法找到答案。
Michael K 2010年

2
我和迈克尔在一起。这是非常全面的。+1从我。
2010年

18

基本上,lambda函数是您“动态”创建的函数。在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(),则该lambda函数相对于它有几个优点:

  • 在调用循环函数的地方指定了在循环中完成的操作
  • 它使您不必编写一些样板代码
  • 在某个名称空间范围内没有函子,使每个人都在查看代码以了解它需要什么

7

Lambda函数是匿名函数的另一个名称-本质上是没有名称的函数。

通常,您可以使用只需要使用一次功能的语言来使用它。例如代替

def add(a, b)
  return a+b

然后将该函数传递给另一个函数

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

使用lambda,您只需做

reduce(lambda x, y: a+b, [5,3,2])
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.