Answers:
简而言之,lambda是没有名称的函数或匿名函数。一小段可执行代码,可以像可变变量一样传递。在JavaScript中:
function () {}; // very simple
现在让我们看看这些lambda的一些用法。
Lambda可以用于提取样板代码。例如循环。我们习惯于整天编写for
和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);
在某些可以使用事件概念的环境中,我们可以使用lambda来响应在某个时间点可能发生的事件。
window.onload = function () {
alert("Loaded");
};
window.setTimeout(function () {
alert("Code executed after 2 seconds.");
}, 2000);
可以用其他方法完成此操作,但是这些方法很冗长。例如,在Java中有Runnable
接口。
在此之前,我们主要仅使用lambda作为其语法糖功能。但是在某些情况下,lambda可能会更有用。例如,我们可能具有返回lambda的函数。假设我们有一个函数,我们希望其返回值被缓存。
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];
};
稍后,我们可能会注意到我们具有类似的功能:
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];
};
显然那里有一个模式,所以让我们对其进行抽象。让我们使用备忘录。
/**
* @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
});
如您所见,通过使用lambda,我们能够抽象出缓存/存储逻辑。如果在另一个示例中有一些变通办法,我相信使用其他技术很难解决这个特定问题。我们设法将一些重要的样板代码提取到一个地方。更不用说我们摆脱了users
和photos
全局变量。
查看您的个人资料,我发现您主要是Python用户。对于上述模式,Python具有装饰器的概念。网上有很多关于记忆修饰器的示例。唯一的区别是,在Python中,您最有可能在该装饰器函数中具有一个命名的嵌套函数。原因是Python仅支持单表达式lambda。但是概念是相同的。
作为Python lambda使用的示例。上面我们过滤了偶数的代码可以在Python中这样表示:
filter(lambda x: x % 2 == 0, [1, 2, 3, 4])
无论如何,如果没有闭包,lambda并不是那么强大。闭包是使lambda的概念如此强大的原因。在我的备忘录示例中,我使用了闭包在store
参数周围创建了一个闭包。这样,即使memoize
函数返回了结果(lambda),我也可以访问该参数。
术语“ lambda”用于指代匿名函数,通常是一个闭包。它们非常有用,因为它们使您可以编写使用其他功能的功能,而不会不必要地膨胀代码。例如,在Ruby中:
(1..100).select {|num| num % 2 == 0}
这将创建一个包含1到100之间的偶数的数组。我们不必写出明确的循环-select方法采用一个函数来测试值,因此我们所需要的只是自定义逻辑。这使我们可以极大地自定义方法,而几乎没有任何工作或开销。基本上,我们可以在较小的函数中组成函数。
那只是他们可以做什么的一个简单例子。作为数据传递功能的能力确实很强大,而功能语言程序员通常会用它做一些令人惊奇的事情。
“ Lambda”可能太少了。看一看Lambda演算。在函数式编程中很有用。
函数式编程是另一种编程范例(如过程式或面向对象的)。
Dobbs Journal博士在一篇有用的文章中介绍了lambda表达式(在C ++的上下文中,但我认为您可以将原理应用于任何语言)。
正如文章所述:“ lambda表达式是一种高度紧凑的表达式,不需要单独的类/函数定义。”
因此,使用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);
这使定义保持内联。
本文还解释了lambda表达式的更多应用。
我认为DDJ文章中的要点是:“通常,在调用站点上需要小的且不太复杂的函数时,将使用lambda表达式。如果该函数不是平凡的,则您不希望使用lambda表达式,而希望使用普通函数或功能对象。”
“ lambda表达式是一个匿名函数,可以包含表达式和语句,并且可以用于创建委托或表达式树类型。
所有lambda表达式都使用lambda运算符=>,该运算符被读取为“ goes to”。lambda运算符的左侧指定输入参数(如果有),而右侧则保存表达式或语句块。读取lambda表达式x => x * x“ x达到x的x倍”。
从MSDN
如果您是Java的开发者,那么在过去的几个月中,您已经听说了很多有关lambda或闭包的信息,因为有不同的建议将此功能添加到Java 7中。提案之一来自Neal Gafter,并在此处进行了详细说明:javac.info。这帮助我了解了用例和优点(尤其是内部类)
对于Java Lambda,这可能是一个很好的起点:
http://rodrigouchoa.wordpress.com/2014/09/10/java-8-lambda-expressions-tutorial/