【问题标题】:What is a lambda and what is an example implementation?什么是 lambda,什么是示例实现?
【发布时间】:2008-12-17 06:49:49
【问题描述】:

我对编程还很陌生,在阅读大量 lambda 概念的同时,不断出现这种概念,但我很难弄清楚它到底是什么,以及实现它将如何让我的编程生活变得如此好多了。那么首先,什么是 lambda,其次它是如何实现的?

感谢所有发帖的人。正如 cmets 中提到的,这是重复的,但是这里有很多很棒的答案,我想为社区保留它们,所以我将其变成了社区帖子。这是另一个问题的链接:

What is a lambda (function)?

【问题讨论】:

  • @rajKumar 你是对的,它可能应该作为重复关闭,但偶尔会很好地获得关于这些主题的新答案,所以我会投票让它保持开放,尽管海报应该已经搜索过问之前
  • @Robert Gould:如果我们要保留重复的问题,最好将它们链接在一起(即在问题正文中放置一个链接)。我会自己做,但我还没有足够的代表。

标签: lambda


【解决方案1】:

Lambda 很难捕捉,但是一旦你描绘了它们,你就无法理解为什么之前没有得到它。

Lamdba 是匿名函数

Lambda 是普通函数,唯一的区别是你没有给它们起名字。

要理解这一点,你必须首先知道,当你创建一个函数时,代码存储在内存中的一个只有计算机知道的地址。

所以当你做这样的事情时:

function Foo ()
{
 /* your code here */
}

您真正要做的是将名称“Foo”绑定到内存中代码的地址。

现在,还有另一种访问地址的方法:references(和指针,但让我们跳过这些讨厌的家伙)

嗯,lambda 函数是一个没有名字的函数,所以它只能通过引用来访问。

你如何使用它们?

当你创建一个 lambda 函数时,你通常只打算使用一次。

一步一步的过程通常是:

  1. 创建函数
  2. 获取参考
  3. 将引用传递到将要使用的地方

最后,引用丢失,函数自动销毁。

典型的用例是回调函数。您在一行中声明、创建和传递函数,因此很方便。

真实单词示例

在 Python 中,您可以在列表推导中使用 lambda:

/* create a list of functions */
function_list = [(lambda x : number_to_add + x) for number_to_add in range(0, 10) ]

在 Javascript 中,您通常将一个函数传递给其他函数。 JQuery 示例:

 $("img").each(

 /* here we pass a function without any name to the "each()" method   */

 function(i){  his.src = "test"   i   ".jpg"; }

 );

你最好知道的事情

  • 一些语言,如 Javascript 或 Lisp,大量使用 拉姆达斯。这可能是出于文化原因,但函数式编程范式往往会导致 lambda-mania。

  • 长 lambda 使代码难以阅读。这就是为什么某些语言限制了 lambda 的可能性,例如 Python 不允许在其中使用“if”语句。

  • Lambda 只是普通函数。无论您在哪里使用,都可以使用普通函数。这只是编码风格的问题。

【讨论】:

  • 我接受了这个答案,因为它对我的菜鸟来说是最清晰的答案。所有其他答案也很出色。
  • -1。 Lambda 并不总是函数。至少在 C# 中,您可以将它们视为表达式树。在这种情况下,就像 LINQ to SQL 一样,不能使用函数来代替。将它们视为数据是它们在 Lisp 甚至 C# 等语言中的特殊之处。
  • 是的,但是您如何向从未使用过简单语言的 lisp 或 LINQ 的人解释这一点?祝你好运。
【解决方案2】:

lambda 是函数的内联描述。它起源于函数式编程语言,而现在支持类似它的其他语言的数量正在增长。这个名字来源于一个叫做 Lambda calculus 的数学东西,它影响了函数式编程语言(如 Lisp),而 lambdas 的想法也来源于它。

您的问题取决于您所谈论的编程语言。例如,在 F# 中,您将使用 fun x -> x * x 来表示

int myfunction(int x) { return x * x; }

在 C# 中,您可以使用 x => x * x 来表示相同的函数。 它的使用方式以及您可以用它做什么很大程度上取决于您使用的语言。

谈到 C#,它们的伟大之处在于能够将它们解析为 表达式树。 lambda 表达式可以用作代码,如 delegate(大致为函数指针)或表达式树中的数据。将它们用作表达式树,使 LINQ to SQL 等库能够使用表达式创建 SQL 语句,以便提交到服务器并获得适当的结果。

【讨论】:

    【解决方案3】:

    Lambda 是一种创建匿名函数或闭包的方法。在命令式语言(和函数式语言)中,它相当于允许嵌套函数,其中内部函数可以访问封闭函数的局部变量和参数。它在关键字lambdafunfn 甚至\ 下出现在函数式语言中;在 Smalltalk 中,它被称为 block。它也存在于大多数脚本语言中,例如 Perl、Python、Lua 等。

    关于没有 lambda 的唯一语言是

    • 没有嵌套函数的语言,例如标准 C 或图标

    • 具有第二类嵌套函数的语言 --- 函数不能从函数返回、存储在全局变量中或存储在堆分配的数据结构中。该语言家族包括 Pascal 及其在 Modula、Ada 和 CLU 家族中的后代。

    Lambda 对程序员和编译器编写者具有重要意义:不再可能将所有局部变量存储在堆栈中。相反,一些变量可能会被捕获并存储在堆分配的闭包中。请注意,当您编写 lambda 时,您正在编写分配

    示例:最简单的函数之一是组合(Haskell 语法):

    compose f g = \x -> f (g x)
    

    这表示compose 接受两个函数fg 作为参数,它返回一个匿名函数,该函数接受它的参数x 然后应用g 然后将f 应用于x . compose 的应用程序创建了一个在堆上分配的闭包,它存储了fg 的值以及指向lambda 主体代码的指针。在 lambda 很常见的语言中,例如 Haskell、ML、Caml 和 Scheme,已经花费了大量的精力使分配速度非常快。一些脚本语言,比如 Lua,有不寻常的实现,它们使非 lambda 的情况与命令式语言中的相同,同时也使 lambda 相当快。 Lambda 在 Smalltalk 中也很快,它也设计用于在堆上分配大量对象。在改进了 lambda 的语言中,例如 Perl 或 Java(内部类与 lambda 相关),费用可能会相对高得多。

    一般来说,如果一种语言在设计时就考虑到了 lambda,那么您可以随心所欲地使用它们。尤其是在 ML、Caml、Scheme、Haskell 中,即使是匿名函数也很便宜——大量使用它们!

    【讨论】:

    • 不错的概述。但是,在下一个 c++ 中,它将创建一个分配在堆栈上的对象,该对象将具有对局部变量的引用,或者保留这些对象的副本(lambda 生命周期必须更长,需要完成副本)并重载 operator()。那里没有明显的性能损失。
    • 您不必等待下一个 C++;这里有完美的 FC++ 库:cc.gatech.edu/~yannis/fc++
    【解决方案4】:

    lambda 在编程世界中意味着一个匿名函数,可以像其他所有普通变量一样传递和返回。所谓的函数式语言内置了它们,但最近有越来越多的语言支持它们,因为它们允许编写可重用的代码。看看这个例子,用下一版本的 C++ 编写:

    // write this once...
    int transform_values(int * values, int n, function<int(int)> f) {
        for(int i = 0; i < n; i++)
            values[i] = f(values[i]);
    }
    
    int values[] = { 1, 2, 3, 4 };
    // ... then call it to double the values in an array
    transform_values(values, 4, [](int v) { return v * 2; });
    

    它在 C# 和其他支持 lambda 的语言中看起来确实很相似。现在有“闭”字。这意味着 lambda 可以捕获局部变量并在计算结果时使用它们:

    int local_variable = 5;
    int values[] = { 1, 2, 3, 4 };
    // ... then call it to multiply the values in an array
    transform_values(values, 4, [=](int v) { return v * local_variable; });
    

    变量local_variable 现在被捕获在闭包内并且可以在其中使用。变量也可以通过闭包来更新。 Lambda 是函数式语言的基本构建块。这是haskell中的一个例子:

    map (\x -> x * 2) [1, 2, 3, 4]
    

    将执行与上面的 C++ 代码相同的操作。它使用给定函数(此处为 lambda)将列表中的值映射到结果列表中。使用 haskell,您可以很好地看到使用的语法如何映射到 Lambda Calculus 的数学概念。

    【讨论】:

      【解决方案5】:

      Lambda 对不同的语言有不同的含义。我在 python 的上下文中了解它们,但我听说 python 的方法与其他语言不同。

      本质上,在 python 中,lambda 是一个匿名函数,只能由一个表达式组成,并返回其结果。

      我知道在其他语言中,它们是更通用的匿名函数,没有单一表达式的限制,但我不确定细节。

      一个匿名函数,就是它听起来的样子。一个没有名字的函数。例如,它们经常用作事件处理程序,或者您需要一个简单的回调函数但又不想弄乱命名空间的任何情况。

      【讨论】:

        【解决方案6】:

        Lambda 是 lambda calculus,但我认为人们将它与术语 closure 互换使用。见What is a Closure?

        Ruby 的实现很容易理解并且非常强大。在下面的代码中,times 方法接受大括号之间的代码块并调用它 HEIGHT 次。您可以定义类似的方法来接受代码块并实现循环构造的东西。

        @cells = []
        HEIGHT.times { @cells << empty_row }
        

        我想如果有一个参数会更有趣。

        5.times { |i| puts i, " " }
        

        【讨论】:

          猜你喜欢
          • 2010-10-12
          • 2019-09-10
          • 1970-01-01
          • 2011-05-27
          • 1970-01-01
          • 1970-01-01
          • 2012-11-20
          相关资源
          最近更新 更多