这个每个人都在说的“Lambda”是什么?

这个每个人都在说的“Lambda”是什么? 很多人似乎都喜欢它,但我可以从中得到的仅仅是将大量代码行填充到单个expression式中的一种方式。

有人可以请教我的真正价值吗?

没有名字的函数

简而言之,lambda是一个没有名字的函数,或者是一个匿名函数。 一小段可执行代码,可以像传递variables一样传递。 在JavaScript中:

function () {}; // very simple 

现在让我们来看看这些lambdaexpression式的一些用法。

抽取样板代码

Lambdas可能被用来抽取样板代码。 例如循环。 我们习惯于整天写和while循环。 但是这是不写的代码。 我们可以提取循环中最重要的部分循环中的代码,并将其余部分抽象出来:

 for (var i=0; i<array.length; i++) { // do what something useful with array[i] } 

通过使用forEach数组对象,变成:

 array.forEach(function (element, index) { // do something useful with element // element is the equivalent of array[i] from above }); 

上面的抽象可能不是那么有用,但是还有其他更高级的函数,比如forEach ,可以执行更多有用的任务。 例如filter

 var numbers = [1, 2, 3, 4]; var even = []; // keep all even numbers from above array for (var i=0; i<numbers.length; i++) { if (numbers[i] % 2 === 0) { even.push(numbers[i]); } } alert(even); // Using the filter method even = [1, 2, 3, 4].filter(function (number) { return number % 2 === 0; }); alert(even); 

代码执行延迟

在一些可以使用事件概念的环境中,我们可以使用lambdas来响应在某个时间点可能发生的事件。

 window.onload = function () { alert("Loaded"); }; window.setTimeout(function () { alert("Code executed after 2 seconds."); }, 2000); 

这可以通过其他方式完成,但是这些过于冗长。 例如,在Java中有Runnable接口。

function工厂

在这之前,我们大多只使用lambda作为其语法糖的能力。 但有些情况下,lambda可以更有用。 例如,我们可能有返回lambdas的函数。 比方说,我们有一个函数,我们希望它的返回值被caching。

 var users = []; var getUser = function (name) { if (! users[name]) { // expensive operations to get a user. Ajax for example users[name] = user_from_ajax; } return users[name]; }; 

稍后,我们可能会注意到我们有一个类似的function:

 var photos = []; var getPhoto = function (name) { if (! photo[name]) { // expensive operations to get a user. Ajax for example photos[name] = photo_from_ajax; } return photos[name]; }; 

那里显然有一个模式,所以让我们把它抽象出来。 让我们使用memoization 。

 /** * @param {Array} store Data structure in which we cache lambda's return values * @param {Function} lambda * @return {Function} A function that caches the result of calling the lambda param */ var memoize = function (store, lambda) { // return a new lambda return function (name) { if (! store[name]) { // Execute the lambda and cache the result store[name] = lambda(name); } return store[name]; }; }; var getUsers = memoize([], function (name) { // expensive operations to get a user. Ajax for example }); var getPhotos = memoize([], function (name) { // expensive operations to get a photo. Ajax for example }); 

正如你所看到的,通过使用lambdas,我们能够抽象出caching/记忆逻辑。 如果对另一个例子有一些解决方法,我相信这个问题很难用其他技术来解决。 我们设法将一些重要的样板代码提取到一个地方。 更何况我们摆脱了usersphotos全局variables。

看着你的个人资料,我发现你主要是一个Python用户。 对于上面的模式,Python有装饰器的概念。 在memoization装饰器的网上有很多的例子 。 唯一的区别是,在Python中,你最有可能在装饰器函数中有一个命名的嵌套函数。 原因是Python只支持单expression式lambdaexpression式。 但是概念是一样的。

作为Python lambda使用的一个例子。 上面的代码我们过滤偶数可以用Python来表示:

 filter(lambda x: x % 2 == 0, [1, 2, 3, 4]) 

无论如何,lambdas没有封闭没有那么强大。 closures是什么使得lambda的概念如此强大。 在我的记忆例子中,我使用闭包在store参数周围创build一个闭包。 这样,即使在memoize函数返回结果(lambda)后,我也可以访问该参数。

术语“lambda”用来指代一个匿名函数,通常是一个闭包 。 它们非常有用,因为它们允许您编写使用其他函数的函数,而不会不必要地膨胀代码。 例如,在Ruby中:

 (1..100).select {|num| num % 2 == 0} 

这将创build一个包含1到100之间偶数的数组。我们不必写出明确的循环–select方法使用一个函数来testing值,所以我们需要的是我们的自定义逻辑。 这使我们能够在几乎不费力气的情况下大大定制方法。 基本上,我们可以用较小的函数来组合函数。

这只是他们可以做的一个简单的例子。 将函数作为数据传递的能力是非常强大的,function性的语言程序员经常用它做一些非常了不起的事情。

“Lambda”可能太less了。 看看Lambda微积分 。 这在函数式编程中很有用。

而函数式编程又是另一种编程范式(如程序或面向对象)。

.NET中的Lambdas通常被称为“语法糖”。 它们不直接影响function,但是它们使语言更易于人们使用。

当你已经理解了使用它们的能力时,我相信你会发现,与使用委托/匿名方法的旧式方式相比,你将会编写更less的代码。

Dobbs Journal博士有一篇有用的文章介绍lambdaexpression式 (在C ++的上下文中,但我认为你可以将这些原则应用于任何语言)。

正如文章所说:“lambdaexpression式是一个非常紧凑的expression式,不需要单独的类/函数定义。”

所以使用DDJ中的列表1和2的例子而不是写:

 std::for_each( vec.begin(), vec.end(), print_to_stream<std::string>(std::cout)); 

这需要一个单独的类定义,如:

 template <typename T, typename Stream> class print_to_stream_t { Stream& stream_; public: print_to_stream_t(Stream& s):stream_(s) {} void operator()(const T& t) const { stream_ << t; } }; template <typename T,typename Stream> print_to_stream_t<T,Stream> print_to_stream(Stream& s) { return print_to_stream_t<T,Stream>(s); } 

使用Boost lambda库可以变成:

 std::for_each(vec.begin(),vec.end(),std::cout << _1); 

这保持内联的定义。

文章还解释了一些更多的lambdaexpression式的应用。

我认为在DDJ文章中的一个关键点是“通常,lambdaexpression式是在调用站点需要小而不是太复杂的函数时使用的,如果函数不平​​凡,则不需要lambdaexpression式,而是一个普通函数或一个函数对象“。

如果你曾经使用过使用函数指针,委托,策略或观察者模式/事件处理的函数/方法,并且认为“我正在编写这个函数只是为了只使用一次 – 把它传递给这个方法;我希望我可以把它写下来,而不是混乱我的代码“ – 这就是您可能使用Lambda函数的地方。 支持这种构造的语言通常也很大程度上利用了传递函数作为参数的概念,特别是在处理列表(一级函数和高阶函数)方面。 function语言尤其如此,它依赖于函数组合而不是内存修改来进行计算。 在某些情况下(使用Python等语言),使用带有列表parsing的lambda函数也被认为比等价的foreach循环更具可读性。

“lambda”词是计算机科学types可能接受math或逻辑训练而不是计算机科学学位的时代的术语。 他们中的一些人制作了一个名为“函数式编程”的范式,与命令式的非常不同,而且非常强大。 AFAIK是该术语开始使用的环境。

math家和逻辑学家被赋予使用奇怪的话。

'lambda'听起来真的很深奥 – 好像它们是非常奇怪和特别的东西。 真的,如果你为Web浏览器应用程序编写JavaScript并使用“var foo = function(){…}”成语,那么你一直在使用lambda函数。

lambdaexpression式是一种简单的函数forms。 这个想法是,左边的forms(相当于参数)的东西变成右边的forms(相当于身体)。

例如,在c sharp:

 x => x * x 

是一个lambda表示一个值。 一些forms的东西

 x 

成为某种forms

 x * x 

“lambdaexpression式是一个可以包含expression式和语句的匿名函数,可以用来创build委托或expression式树types。

所有的lambdaexpression式都使用lambda运算符=>,读作“去”。 lambda运算符的左侧指定input参数(如果有的话),右侧保存expression式或语句块。 将lambdaexpression式x => x * x读取为“x转到x次x”。

从MSDN

有关Lambdaexpression式的完整说明,请查看维基百科 。 (向下滚动到Lambda微积分和编程语言部分。)Lambdaexpression式不是那么新,它们不仅仅是C#的一部分,而是80年前已经被引入到计算中的东西! Lambdaexpression式是函数式编程的基础。

这是价值? 那么,考虑到它实际上是相当古老的,我会说:对于任何人进行计算非常有价值。

如果您使用的是Java,那么您在过去的几个月里就已经了解了很多关于lambdas或closures的内容,因为在Java 7中添加了这个特性的build议有所不同。但是,我认为comitee会抛弃它。 其中一个build议来自Neal Gafter,并在这里详细解释: javac.info 。 这帮助我理解了用例和优点(特别是内部类)

是的,这只是将大量代码行填充到单个expression式中的一种方法。 但是如此高效的填充,它使一些新的方法来构build你的程序。

通常会避免编写委托或callback,并回到过程风格,因为为单个expression式声明新的函数或类太繁重了。

Lambdaexpression式使得值得使用callback,即使是最小的任务,这可能会使代码更清晰。 也许不会。

你会发现所有你需要知道的(关于C#Lambdas)在这里开始:
Lambdaexpression式

对于java lambda,这可能是一个很好的起点:

http://rodrigouchoa.wordpress.com/2014/09/10/java-8-lambda-expressions-tutorial/