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


93

每个人都在说什么“ Lambda”?很多人似乎都喜欢它,但是我可以从中收集到的只是这是将很多代码行挤入一个表达式中的一种方式。

有人可以启发我了解它的真正价值吗?


16
我可以指出来应答者的提问无处提到.NET


破解问题。感谢您的询问。
花生

Lambda属于函数式编程(声明性编程)领域。
RBT

Answers:


179

没有名称的功能

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

function () {}; // very simple

现在让我们看看这些lambda的一些用法。

抽象样板代码

Lambda可以用于提取样板代码。例如循环。我们习惯于整天编写forwhile循环。但这是未编写的代码。我们可以将代码提取到循环中,这是循环中最重要的部分,然后将其余部分抽象化:

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,我们能够抽象出缓存/存储逻辑。如果在另一个示例中有一些变通办法,我相信使用其他技术很难解决这个特定问题。我们设法将一些重要的样板代码提取到一个地方。更不用说我们摆脱了usersphotos全局变量。

查看您的个人资料,我发现您主要是Python用户。对于上述模式,Python具有装饰器的概念。网上有很多关于记忆修饰器的示例。唯一的区别是,在Python中,您最有可能在该装饰器函数中具有一个命名的嵌套函数。原因是Python仅支持单表达式lambda。但是概念是相同的。

作为Python lambda使用的示例。上面我们过滤了偶数的代码可以在Python中这样表示:

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

无论如何,如果没有闭包,lambda并不是那么强大。闭包是使lambda的概念如此强大的原因。在我的备忘录示例中,我使用了闭包在store参数周围创建了一个闭包。这样,即使memoize函数返回了结果(lambda),我也可以访问该参数。


3
哇,你花了很多时间。
9

4
@ Mk12,在答案的实际写作中,不是真的。是的,自从我开始学习以来,已经有一段时间了:)
Ionuț G. Stan

好的答案,但是缺少有关“功能接口”的信息(从Java的角度来看)。
djangofan 2013年

您的“抽象样板代码”中的那些“ ===”运算符是什么?


19

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

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

这将创建一个包含1到100之间的偶数的数组。我们不必写出明确的循环-select方法采用一个函数来测试值,因此我们所需要的只是自定义逻辑。这使我们可以极大地自定义方法,而几乎没有任何工作或开销。基本上,我们可以在较小的函数中组成函数。

那只是他们可以做什么的一个简单例子。作为数据传递功能的能力确实很强大,而功能语言程序员通常会用它做一些令人惊奇的事情。


6
也许您应该补充一点,管道中的东西是参数。我是阅读红宝石有困难的人之一。
Skurmedel

这是一个很好的答案。Ionut获得投票的唯一原因是他告诉我们为什么我们应该(详细)关心lambda。
Frank Shearar,2009年

我不同意lambda通常是闭包。
2013年

6

“ Lambda”可能太少了。看一看Lambda演算。在函数式编程中很有用。

函数式编程是另一种编程范例(如过程式或面向对象的)。


5
然后人们谈论“ Lambda”,最有可能的是他们在谈论匿名函数,函数指针,闭包或类似的东西。几乎从来没有提到真正的lambda演算。
J-16 SDiZ 09年

很高兴您提到了Lambda演算。+1。
RBT

5

.NET中的Lambda经常被称为“语法糖”。它们不会直接影响功能,但是会使人们更容易使用该语言。

当您了解使用它们的功能后,我相信与使用委托/匿名方法的旧样式相比,您将编写的代码更少。


1
我认为没有人提到.NET,因此使用更通用的答案可能会更好。
molf

2
这就是为什么我通过回答有关.net的方式进行澄清的原因。如果其他人对他们的语言实现感到兴奋,那么无论他们选择哪种语言,问答都将帮助许多人。
redsquare

这个答案听起来像是您听说过有关lambda的内容,但是您自己还不了解它们。
2013年

2

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表达式,而希望使用普通函数或功能对象。”


2

如果您曾经使用过使用函数指针,委托,策略或观察者模式/事件处理的函数/方法,并且对自己说:“我正在编写整个函数,只使用一次-将其传递给此方法;我希望我可以就地编写它,而不要使我的代码变得混乱”,这就是您可以使用Lambda函数的地方。支持此构造的语言通常还大量利用将函数作为参数传递的概念,特别是在处理列表(一级函数和高阶函数)方面。对于依赖于函数组成而不是进行内存修改的函数式语言而言,尤其如此。在某些情况下(使用Python等语言),


2

“ lambda”一词是从计算机科学类型受过数学或逻辑训练的程度比拥有计算机科学学位的年代起的术语。他们中的一些人编写了一个称为“函数式编程”的范例,它与命令式命令完全不同,功能也非常强大。AFAIK是该术语使用的环境。

数学家和逻辑学家被赋予使用怪异的词语的能力。

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


1

Lambda表达式是函数的一种简单形式。这个想法是,左侧的某种形式(等同于参数)变成右侧的某种形式(等同于主体)。

例如,在c Sharp中:

x => x * x

是一个平方值的lambda。形式的东西

x

变成某种形式

x * x

0

“ lambda表达式是一个匿名函数,可以包含表达式和语句,并且可以用于创建委托或表达式树类型。

所有lambda表达式都使用lambda运算符=>,该运算符被读取为“ goes to”。lambda运算符的左侧指定输入参数(如果有),而右侧则保存表达式或语句块。读取lambda表达式x => x * x“ x达到x的x倍”。

MSDN


4
是的,微软让每个人都认为自己已经发明了它。不过,Lambda表达式早于Microsoft。这是一个数学术语,已应用于多种编程语言。(这是可能的,因为数学本身可以被认为是一种计算机语言。)
Wim 10 Brink

4
请注意,这特定于Microsoft的.Net实现。与lambda的一般概念并没有很大的偏差,但我认为Lisp中实现的功能更“标准”。
Chuck

2
这个答案根本无法解释Lambda是什么(需要定义匿名函数,委托,表达式树类型),当然也不能解释其价值。
2009年

0

有关Lambda表达式的完整说明,请参阅Wikipedia。(向下滚动至Lambda演算和编程语言部分。)Lambda表达式并不是新的内容,它们不仅是C#的一部分,而且是将近80年前引入计算的东西!Lambda表达式是函数编程的基础。

值吗?好吧,考虑到它实际上已经很老了,我想说:对于任何进行计算的人都非常有价值。


0

如果您是Java的开发者,那么在过去的几个月中,您已经听说了很多有关lambda或闭包的信息,因为有不同的建议将此功能添加到Java 7中。提案之一来自Neal Gafter,并在此处进行了详细说明:javac.info。这帮助我了解了用例和优点(尤其是内部类)




-1

是的,这只是将很多代码行挤入一个表达式中的一种方法。但是,由于这种高效的填塞,它启用了一些新的程序结构方式。

通常,一个人会避免编写委托或回调并返回到过程样式,这仅仅是因为为单个表达式声明新函数或类太繁琐了。

Lambda表达式使即使是最微小的任务也可以使用回调,这可能使代码更清晰。可能不会。

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.