什么是lambda(函数)?

对于一个没有comp-sci背景的人来说,在计算机科学世界里什么是lambda?

Lambda来自Lambda微积分 ,指的是编程中的匿名函数。

为什么这很酷? 它可以让你写快速扔掉的function,而无需命名。 它还提供了一个写封闭的好方法。 有了这个力量,你可以做这样的事情。

python

def adder(x): return lambda y: x + y add5 = adder(5) add5(1) 6 

正如你可以从Python的片段中看到的,函数加法器接受一个参数x,并返回一个匿名函数或lambda,它接受另一个参数y。 匿名函数允许您从函数创build函数。 这是一个简单的例子,但它应该传达权力lambdas和封闭有。

其他语言的示例

JavaScript的

 var adder = function (x) { return function (y) { return x + y; }; }; add5 = adder(5); add5(1) == 6 

JavaScript(ES6)

 const adder = x => y => x + y; add5 = adder(5); add5(1) == 6 

scheme

 (define adder (lambda (x) (lambda (y) (+ xy)))) (define add5 (adder 5)) (add5 1) 6 

C#3.5或更高版本

 Func<int, Func<int, int>> adder = (int x) => (int y) => x + y; // `int` declarations optional Func<int, int> add5 = adder(5); var add6 = adder(6); // Using implicit typing Debug.Assert(add5(1) == 6); Debug.Assert(add6(-1) == 5); // Closure example int yEnclosed = 1; Func<int, int> addWithClosure = (x) => x + yEnclosed; Debug.Assert(addWithClosure(2) == 3); 

迅速

 func adder(x: Int) -> (Int) -> Int{ return { y in x + y } } let add5 = adder(5) add5(1) 6 

PHP

 $a = 1; $b = 2; $lambda = function () use (&$a, &$b) { echo $a + $b; }; echo $lambda(); 

哈斯克尔

 (\xy -> x + y) 

Java的

看到 这个职位

 // The following is an example of Predicate : // a functional interface that takes an argument // and returns a boolean primitive type. Predicate<Integer> pred = x -> x % 2 = 0; // Tests if the parameter is even. boolean result = pred.test(4); // true 

LUA

 adder = function(x) return function(y) return x + y end end add5 = adder(5) add5(1) == 6 -- true 

lambda是一种内联定义的函数。 随着一个lambda你通常也有某种variablestypes可以容纳一个函数,lambda或其他的引用。

例如,下面是一个不使用lambda的C#代码:

 public Int32 Add(Int32 a, Int32 b) { return a + b; } public Int32 Sub(Int32 a, Int32 b) { return a - b; } public delegate Int32 Op(Int32 a, Int32 b); public void Calculator(Int32 a, Int32 b, Op op) { Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b)); } public void Test() { Calculator(10, 23, Add); Calculator(10, 23, Sub); } 

这叫计算器,传递不只是两个数字,而是计算器里面调用哪个方法来获得计算结果。

在C#2.0中,我们得到了匿名方法,它将上面的代码缩短为:

 public delegate Int32 Op(Int32 a, Int32 b); public void Calculator(Int32 a, Int32 b, Op op) { Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b)); } public void Test() { Calculator(10, 23, delegate(Int32 a, Int32 b) { return a + b; }); Calculator(10, 23, delegate(Int32 a, Int32 b) { return a - b; }); } 

然后在C#3.0中,我们得到了使代码更短的lambdas:

 public delegate Int32 Op(Int32 a, Int32 b); public void Calculator(Int32 a, Int32 b, Op op) { Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b)); } public void Test() { Calculator(10, 23, (a, b) => a + b); Calculator(10, 23, (a, b) => a - b); } 

它指的是lambda微积分 ,它是一个只有lambdaexpression式的forms系统,它表示一个函数,它为其唯一参数提供一个函数并返回一个函数。 λ演算中的所有函数都是这种types的,即λ : λ → λ

Lisp使用lambda概念来命名匿名函数文字。 这个lambda表示一个函数,它接受两个参数x和y,并返回它们的产品:

 (lambda (xy) (* xy)) 

它可以像这样在线应用(评估为50 ):

 ((lambda (xy) (* xy)) 5 10) 

名字“lambda”只是一个历史的神器。 我们所谈论的是一个expression式,其值是一个函数。

一个简单的例子(在下一行使用Scala)是:

 args.foreach(arg => println(arg)) 

其中foreach方法的参数是匿名函数的expression式。 上面的代码与写这样的代码差不多(不太真实的代码,但是你会明白):

 void printThat(Object that) { println(that) } ... args.foreach(printThat) 

除了你不需要打扰:

  1. 在其他地方声明函数(以后再次访问代码时必须查找它)。
  2. 命名你只用了一次的东西。

一旦你习惯了函数值,如果没有它们,那么看起来就像命名每个expression式一样愚蠢,比如:

 int tempVar = 2 * a + b ... println(tempVar) 

而不是仅仅在需要的地方写下expression式:

 println(2 * a + b) 

确切的符号因语言而异; 希腊并不总是必需的! 😉

lambda演算是一个一致的math替代理论。 在学校的math中,例如x+y=5x−y=1配对。 除了操纵单个方程式的方法之外,还可以将来自这两个方程的信息放在一起,只要逻辑地完成交叉方程replace。 Lambda演算编码正确的方法来做这些replace。

假设y = x−1是第二个方程的有效重排,这个: λ y = x−1意味着用符号x−1代替符号y的函数。 现在设想在第一个方程中对每个项应用λ y 。 如果一个术语是y则执行replace; 否则什么都不做。 如果你在纸上这样做,你会看到如何应用λ y将使第一个方程可解。

这是没有任何计算机科学或编程的答案。

我能想到的最简单的编程示例来自http://en.wikipedia.org/wiki/Joy_(programming_language)#How_it_works

这里是如何在命令式编程语言(C)中定义平方函数:

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

variablesx是一个forms参数,被函数调用时的实际值取平方。 在函数式语言(Scheme)中,将定义相同的函数:

 (define square (lambda (x) (* xx))) 

这在很多方面是不同的,但它仍然以相同的方式使用forms参数x。


补充: http : //imgur.com/a/XBHub

拉姆达

略显过于简单:lambda函数是一个可以传递给其他函数的函数,它的逻辑访问。

在C#中,lambda语法通常以与匿名委托相同的方式编译为简单方法,但也可以将其分解并将其逻辑读取。

例如(在C#3中):

 LinqToSqlContext.Where( row => row.FieldName > 15 ); 

LinqToSql可以读取该函数(x> 15)并将其转换为使用expression式树执行的实际SQL。

以上声明变成:

 select ... from [tablename] where [FieldName] > 15 --this line was 'read' from the lambda function 

这不同于一般的方法或匿名委托(它们真的只是编译器的魔术),因为它们不能被读取

并非所有使用lambda语法的C#中的方法都可以编译为expression式树(即实际的lambda函数)。 例如:

 LinqToSqlContext.Where( row => SomeComplexCheck( row.FieldName ) ); 

现在expression式树不能被读取 – SomeComplexCheck不能被分解。 SQL语句将在没有where的地方执行,并且数据中的每一行都将通过SomeComplexCheck

Lambda函数不应与匿名方法混淆。 例如:

 LinqToSqlContext.Where( delegate ( DataRow row ) { return row.FieldName > 15; } ); 

这也有一个'inline'函数,但是这一次只是编译器的魔力 – C#编译器会把它分解成一个自动生成名称的新实例方法。

匿名方法不能被读取,所以逻辑不能像lambda函数那样被翻译出来。

我喜欢在本文中对Lambdas的解释: LINQ的演变及其对C#devise的影响 。 这对我来说很有意义,因为它展示了一个真实的兰姆达斯世界,并将其作为一个实际的例子。

他们的快速解释:Lambdas是一种将代码(函数)视为数据的方式。

Ruby中的lambda示例如下所示:

 hello = lambda do puts('Hello') puts('I am inside a proc') end hello.call 

将生成以下输出:

 Hello I am inside a proc 

@Brian在LINQ和非LINQ运算符中,我总是在C#中使用lambdas。 例:

 string[] GetCustomerNames(IEnumerable<Customer> customers) { return customers.Select(c=>c.Name); } 

在C#之前,我使用JavaScript中的匿名函数来callbackAJAX函数,甚至在创造Ajax这个术语之前:

 getXmlFromServer(function(result) {/*success*/}, function(error){/*fail*/}); 

然而,C#的lambda语法有趣的是,它们自己的types不能被传递(即,你不能inputvar foo =(x,y)=> x * y),但是取决于它们是哪种types分配给它们,它们将被编译为表示expression式的代表或抽象语法树(这是LINQ对象映射器如何执行其“语言集成”魔术)。

LISP中的Lambdas也可以传递给引用操作符,然后遍历为列表的列表。 一些强大的macros是这样做的。

你可以把它看作一个匿名函数 – 这里有一些更多的信息: 维基百科 – 匿名函数

这个问题正式得到了很好的回答,所以我不会在这个问题上增加更多的内容。

对于那些对math或编程知之甚less或根本不知道的人来说,非常简单, 非正式的话,我会把它解释为一个小型的“机器”或“盒子”,它需要一些input,做一些工作,产生一些输出,没有特定的名字,但是我们知道它在哪里,通过这个知识,我们使用它。

实际上,对于一个知道一个函数是什么的人来说,我会告诉他们这个函数没有名字,通常只能通过引用该内存来使用内存中的某一点(通常是通过使用一个variables – 如果他们已经听说过函数指针的概念,我会用它们作为一个类似的概念) – 这个答案涵盖了相当的基础知识(没有提到闭包等),但是可以很容易地理解这个问题。

我在包装lambdaexpression式的时候遇到了麻烦,因为我在Visual FoxPro中工作,它具有macrosreplace和ExecScript {}和Evaluate()函数,这些函数似乎有着相同的用途。

 ? Calculator(10, 23, "a + b") ? Calculator(10, 23, "a - b"); FUNCTION Calculator(a, b, op) RETURN Evaluate(op) 

使用正式的lambdaexpression式的一个肯定的好处是(我假设)编译时检查:Fox不会知道是否键入上面的文本string,直到它试图运行它。

这对数据驱动代码也很有用:您可以将整个例程存储在数据库的备注字段中,然后在运行时对其进行评估。 这使您可以调整应用程序的一部分,而无需实际访问源代码。 (但这是另一个话题。)

只是因为我不能在这里看到一个C ++ 11的例子,我会继续前进,从这里发布这个很好的例子。 经过search,这是我能find的最清晰的语言范例。

你好,Lambdas,版本1

 template<typename F> void Eval( const F& f ) {   f(); } void foo() {   Eval( []{printf("Hello, Lambdas\n");} ); } 

你好,Lambdas,版本2:

 void bar() {   auto f = []{printf("Hello, Lambdas\n"); };   f(); } 

这是一个没有名字的函数。 例如在C#中,你可以使用

 numberCollection.GetMatchingItems<int>(number => number > 5); 

返回大于5的数字。

 number => number > 5 

这里是lambda部分。 它表示一个函数,它接受一个参数(数字)并返回一个布尔值(数字> 5)。 GetMatchingItems方法在集合中的所有项目上使用这个lambda,并返回匹配的项目。

我也是。 我已经用JS试了一下:

 var addAndMult = function(x) { return (function(y) { return (function(z) { return (x+y)*z; }); }); }; 

它增加了2到4,然后是6的结果。然而,我发现它有时很难读:

另外我为每个function做了一个有趣的事情:

 var forEach = function(arr) { return (function(x) { for (var i=0; arr[i]; i++) { x(arr[i]); } }); } 

的forEach([1,2,3,4,5])(的console.log);

此方法将迭代一个数组并执行一个操作 – 在打印到控制台的情况下。 现在我也明白为什么labmdas是强大的。

例如,在Javascript中,函数被视为与其他一切( intstringfloatbool )相同的混合types。 因此,您可以即时创buildfunction,将它们分配给事物,并在稍后调用它们。 这是有用的,但不是你想要过度使用,或者你会混淆每个人必须维护你的代码后…

这是我正在玩的一些代码,看看这个兔子洞有多深:

 var x = new Object; x.thingy = new Array(); x.thingy[0] = function(){ return function(){ return function(){ alert('index 0 pressed'); }; }; } x.thingy[1] = function(){ return function(){ return function(){ alert('index 1 pressed'); }; }; } x.thingy[2] = function(){ return function(){ return function(){ alert('index 2 pressed'); }; }; } for(var i=0 ;i<3; i++) x.thingy[i]()()(); 

在CS的背景下,lambda函数是一个抽象的math概念,用于解决mathexpression式的符号评估问题。 在这种情况下,lambda函数与lambda项相同。

但是在编程语言中,它有些不同。 这是一段被宣布为“到位”的代码,可以作为“一等公民”来传递。 这个概念似乎很有用,因此它几乎可以应用到所有stream行的现代编程语言中(参见后期的lambda函数 )。

在计算机编程中,lambda是一段代码(语句,expression式或它们的组合),它从外部源获取一些参数。 它不一定总是一个匿名函数 – 我们有很多方法来实现它们。

我们在expression式,陈述和函数之间有明确的分离,这是math家所没有的。

编程中的“function”这个词也是不同的 – 我们有“function是一系列的步骤”(来自拉丁语“执行”)。 在math中它是关于variables之间的相关性的东西。

函数式语言试图尽可能地和math公式类似,他们的话几乎相同。 但在其他编程语言中,我们有不同的。