我对编程相当陌生,在阅读大量 lambda 概念的同时,不断出现这种概念,但我很难弄清楚它实际上是什么,以及如何实现它将使我的编程生活变得更好。那么首先,什么是 lambda,其次它是如何实现的?
感谢所有发帖的人。正如评论中提到的,这是重复的,但是这里有很多很棒的答案,我想为社区保留它们,所以我将它变成了社区帖子。这是另一个问题的链接:
我对编程相当陌生,在阅读大量 lambda 概念的同时,不断出现这种概念,但我很难弄清楚它实际上是什么,以及如何实现它将使我的编程生活变得更好。那么首先,什么是 lambda,其次它是如何实现的?
感谢所有发帖的人。正如评论中提到的,这是重复的,但是这里有很多很棒的答案,我想为社区保留它们,所以我将它变成了社区帖子。这是另一个问题的链接:
Lambda 很难捕捉,但一旦你描绘了它们,你就无法理解为什么以前没有得到它。
Lambda 是普通函数,唯一的区别是你没有给它们命名。
要理解这一点,您必须首先知道,当您创建一个函数时,代码存储在内存中的一个只有计算机知道的地址。
所以当你做这样的事情时:
function Foo ()
{
/* your code here */
}
您真正要做的是将名称“Foo”绑定到内存中代码的地址。
现在,还有另一种访问地址的方法:引用(和指针,但让我们跳过这个讨厌的家伙)
嗯,一个 lambda 函数是一个没有名字的函数,所以它只能通过它的引用来访问。
创建 lambda 函数时,通常只计划使用一次。
一步一步的过程通常是:
最后,引用丢失,因此函数被自动销毁。
典型的用例是回调函数。您在一行中声明、创建和传递函数,因此很方便。
在 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。这可能是出于文化原因,但函数式编程范式往往会导致 lambda 狂热。
长 lambdas 使代码难以阅读。这就是为什么某些语言限制了 lambdas 的可能性,例如不允许在其中使用“if”语句的 Python。
Lambda 只是普通函数。无论您在哪里使用,都可以使用普通函数。这只是编码风格的问题。
lambda 是函数的内联描述。它起源于函数式编程语言,而现在支持类似它的其他语言的数量正在增长。这个名字来自一个叫做 Lambda 演算的数学东西,它影响了函数式编程语言(例如 Lisp),而 lambdas 的想法也来自它。
您的问题取决于您正在谈论的编程语言。例如,在 F# 中,您将使用fun x -> x * x
来表示
int myfunction(int x) { return x * x; }
在 C# 中,您将使用x => x * x
来表示相同的函数。它的使用方式以及您可以用它做什么几乎取决于您使用的语言。
谈到 C#,关于它们的伟大之处在于能够将它们解析为表达式树。lambda 表达式可以用作代码,如委托(大致是函数指针)或表达式树中的数据。将它们用作表达式树,使 LINQ to SQL 等库能够使用表达式创建 SQL 语句,以便提交到服务器并获得适当的结果。
Lambda 是一种创建匿名函数或闭包的方法。在命令式语言(和函数式语言)中,它等效于允许嵌套函数,其中内部函数可以访问封闭函数的局部变量和参数。它在函数式语言中的关键字lambda
,甚至;下找到fun
。在 Smalltalk 中它被称为块。它也存在于大多数脚本语言中,例如 Perl、Python、Lua 等。fn
\
关于没有lambda 的唯一语言是
没有嵌套函数的语言,例如标准 C 或图标
具有二等嵌套函数的语言——一个函数不能从函数返回,不能存储在全局变量中,也不能存储在堆分配的数据结构中。该语言家族包括 Pascal 及其在 Modula、Ada 和 CLU 家族中的后代。
Lambda 对程序员和编译器编写者具有重要意义:不再可能将所有局部变量存储在堆栈上。相反,可以捕获一些变量并将其存储在堆分配的闭包中。请注意,当您编写 lambda 时,您正在编写分配。
示例:最简单的函数之一是组合(Haskell 语法):
compose f g = \x -> f (g x)
这表示compose
接受两个函数f
和g
作为参数,它返回一个匿名函数,该函数接受它的参数,x
然后应用到. 的应用程序创建一个分配在堆上的闭包,该闭包存储 和 的值以及指向 lambda 主体代码的指针。在 lambda 很常见的语言中,例如 Haskell、ML、Caml 和 Scheme,已经花费了大量的精力来使分配速度非常快g
f
x
compose
f
g
. 一些脚本语言,比如 Lua,有不寻常的实现,它们使非 lambda 的情况与命令式语言中的情况相同,同时也使 lambda 相当快。Lambda 在 Smalltalk 中也很快,它也被设计为在堆上分配大量对象。在改进了 lambda 的语言中,例如 Perl 或 Java(内部类与 lambda 相关),费用可能相对高得多。
一般来说,如果一种语言在设计时考虑到了 lambda,那么您可以随心所欲地使用它们。尤其是在 ML、Caml、Scheme、Haskell 中,即使是匿名函数也非常便宜——大量使用它们!
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 演算的数学概念。
Lambda 是lambda calculus,但我认为人们可以将它与闭包一词互换使用。请参阅什么是闭包?
Ruby 的实现很容易理解并且非常强大。在下面的代码times
方法中,接受大括号之间的代码块并调用它HEIGHT
。您可以定义接受代码块并实现循环构造的类似方法。
@cells = []
HEIGHT.times { @cells << empty_row }
我想如果有一个参数会更有趣。
5.times { |i| puts i, " " }
Lambda 对不同的语言有不同的含义。我在 python 的上下文中了解它们,但我听说 python 与其他语言有不同的方法。
本质上,在 python 中,lambda 是一个匿名函数,只能由一个表达式组成,并返回其结果。
我知道在其他语言中,它们是更通用的匿名函数,没有单一表达式的限制,但我不确定细节。
一个匿名函数,就是它听起来的样子。一个没有名字的函数。例如,它们经常用作事件处理程序,或者您需要一个简单的回调函数但又不想弄乱命名空间的任何情况。