What is a lambda (function)?
对于一个没有计算机科学背景的人来说,计算机科学界的lambda是什么?
lambda来自lambda微积分,在编程中引用匿名函数。
为什么这么酷?它允许您在不命名的情况下编写快速丢弃函数。它还提供了一种编写闭包的好方法。有了这种能力,你就可以做这样的事情。
Python
1 2 3 4 5 | def adder(x): return lambda y: x + y add5 = adder(5) add5(1) 6 |
从python的片段中可以看到,函数adder接受一个参数x,并返回一个匿名函数或lambda,它接受另一个参数y。该匿名函数允许您从函数创建函数。这是一个简单的例子,但它应该传递lambda和闭包所具有的强大功能。
其他语言示例
Perl 5
1 2 3 4 5 6 7 8 9 10 11 12 | sub adder { my ($x) = @_; return sub { my ($y) = @_; $x + $y } } my $add5 = adder(5); print &$add5(1) == 6 ?"ok " :"not ok "; |
JavaScript
1 2 3 4 5 6 7 | var adder = function (x) { return function (y) { return x + y; }; }; add5 = adder(5); add5(1) == 6 |
JavaScript(ES6)
1 2 3 | const adder = x => y => x + y; add5 = adder(5); add5(1) == 6 |
方案
1 2 3 4 5 6 7 8 | (define adder (lambda (x) (lambda (y) (+ x y)))) (define add5 (adder 5)) (add5 1) 6 |
C 3.5或更高
1 2 3 4 5 6 7 8 9 10 11 12 | 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); |
迅捷
1 2 3 4 5 6 | func adder(x: Int) -> (Int) -> Int{ return { y in x + y } } let add5 = adder(5) add5(1) 6 |
PHP
1 2 3 4 5 6 7 8 | $a = 1; $b = 2; $lambda = function () use (&$a, &$b) { echo $a + $b; }; echo $lambda(); |
哈斯克尔
1 | (\x y -> x + y) |
Java看到这个帖子
1 2 3 4 5 6 | // 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 |
卢阿
1 2 3 4 5 6 7 | adder = function(x) return function(y) return x + y end end add5 = adder(5) add5(1) == 6 -- true |
科特林
1 2 | val pred = { x: Int -> x % 2 == 0 } val result = pred(4) // true |
红宝石
Ruby略有不同,因为您不能使用与调用函数完全相同的语法来调用lambda,但它仍然有lambda。
1 2 3 4 5 | def adder(x) lambda { |y| x + y } end add5 = adder(5) add5[1] == 6 |
Ruby是Ruby,有一个lambdas的缩写,所以您可以这样定义
1 2 3 | def adder(x) -> y { x + y } end |
lambda是内联定义的函数类型。除了lambda之外,通常还具有某种类型的变量,可以保存对函数、lambda或其他类型的引用。
例如,这里有一段不使用lambda的C代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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中,我们使用匿名方法,将上述代码缩短为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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中,我们得到了lambda,这使得代码更短:
1 2 3 4 5 6 7 8 9 10 11 12 | 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微积分,它是一个只有lambda表达式的形式系统,它表示一个函数,它接受一个函数作为它的唯一参数并返回一个函数。lambda演算中的所有函数都是这种类型,即
Lisp使用lambda概念命名其匿名函数文本。此lambda表示一个函数,该函数接受两个参数x和y,并返回其乘积:
1 | (lambda (x y) (* x y)) |
它可以这样在线应用(评估值为50):
1 | ((lambda (x y) (* x y)) 5 10) |
名称"lambda"只是一个历史产物。我们所说的是一个表达式,它的值是一个函数。
一个简单的例子(将scala用于下一行)是:
1 | args.foreach(arg => println(arg)) |
其中,
1 2 3 4 5 | void printThat(Object that) { println(that) } ... args.foreach(printThat) |
除此之外,您不必费心:
一旦习惯了对值进行函数运算,没有这些值就好像被要求命名每个表达式一样愚蠢,比如:
1 2 3 | int tempVar = 2 * a + b ... println(tempVar) |
而不仅仅是在需要的地方编写表达式:
1 | println(2 * a + b) |
确切的符号因语言而异;并不总是需要希腊语!;-)
lambda演算是一个一致的数学替换理论。在学校数学中,我们可以看到例如
考虑到
这是一个没有任何计算机科学或编程的答案。
我能想到的最简单的编程示例来自http://en.wikipedia.org/wiki/joy_u(编程语言)它是如何工作的:
here is how the square function might be defined in an imperative
programming language (C):
1
2
3
4 int square(int x)
{
return x * x;
}The variable x is a formal parameter which is replaced by the actual
value to be squared when the function is called. In a functional
language (Scheme) the same function would be defined:
1
2
3 (define square
(lambda (x)
(* x x)))This is different in many ways, but it still uses the formal parameter
x in the same way.
添加:http://imgur.com/a/xbhub
稍微过于简单:lambda函数可以传递给其他函数,并且可以访问它的逻辑。
在C lambda中,语法通常以与匿名委托相同的方式编译为简单方法,但它也可以分解并读取逻辑。
例如(在c 3中):
1 2 | LinqToSqlContext.Where( row => row.FieldName > 15 ); |
LinqToSQL可以读取该函数(x>15),并将其转换为实际的SQL,以便使用表达式树执行。
上述声明为:
1 2 | select ... from [tablename] where [FieldName] > 15 --this line was 'read' from the lambda function |
这与普通方法或匿名委托(实际上只是编译器的魔力)不同,因为它们不能被读取。
并非所有使用lambda语法的c中的方法都可以编译为表达式树(即实际lambda函数)。例如:
1 2 | LinqToSqlContext.Where( row => SomeComplexCheck( row.FieldName ) ); |
现在无法读取表达式树-SomeComplexCheck无法分解。SQL语句将不使用WHERE执行,数据中的每一行都将通过
lambda函数不应与匿名方法混淆。例如:
1 2 3 4 | LinqToSqlContext.Where( delegate ( DataRow row ) { return row.FieldName > 15; } ); |
这也有一个"inline"函数,但这一次它只是编译器的魔力——C编译器将把它拆分成一个新的实例方法,并使用一个自动生成的名称。
无法读取匿名方法,因此无法像对lambda函数那样转换逻辑。
我喜欢本文中关于lambdas的解释:linq的演变及其对c设计的影响。这对我来说很有意义,因为它为兰姆达斯展示了一个真实的世界,并将其作为一个实际的例子加以构建。
他们的快速解释:lambda是一种将代码(函数)视为数据的方法。
Ruby中lambda的示例如下:
1 2 3 4 5 6 | hello = lambda do puts('Hello') puts('I am inside a proc') end hello.call |
将生成以下输出:
1 2 | Hello I am inside a proc |
这个问题得到了正式的回答,所以我不会再多加一点。
对于一个对数学或编程知之甚少或一无所知的人来说,我用一个非常简单的非正式词汇,把它解释为一个小的"机器"或"盒子",它接受一些输入,做一些工作,产生一些输出,没有特定的名称,但我们知道它在哪里,仅凭这个知识,我们就使用它。
实际上,对于一个知道函数是什么的人,我会告诉他们,它是一个没有名字的函数,通常放在内存中的一个点上,可以通过引用该内存来使用(通常通过变量的使用-如果他们听说过函数指针的概念,我会把它们作为类似的概念使用)。-这个答案涵盖了相当基础的内容(没有提到闭包等),但是我们可以很容易地理解这一点。
@布莱恩,我一直在用C,LINQ和非LINQ操作符。例子:
1 2 3 | string[] GetCustomerNames(IEnumerable<Customer> customers) { return customers.Select(c=>c.Name); } |
在c之前,我在javascript中使用匿名函数回调Ajax函数,甚至在术语Ajax出现之前:
1 | getXmlFromServer(function(result) {/*success*/}, function(error){/*fail*/}); |
不过,C的lambda语法的有趣之处在于,它们本身的类型无法推断(即,您不能键入var foo=(x,y)=>x*y),但根据它们被分配到的类型,它们将被编译为表示表达式的委托或抽象语法树(这就是Linq对象映射器如何进行"语言集成"的方式)。"魔法"。
Lisp中的lambda也可以传递给报价运算符,然后作为列表列表进行遍历。一些强大的宏是这样生成的。
你可以把它看作一个匿名函数-这里有更多的信息:维基百科-匿名函数
只是因为我看不到这里的C++ 11例子,所以我会在这里发布这个好的例子。在搜索之后,它是我能找到的最清晰的语言特定的例子。
你好,兰姆达斯,版本11 2 3 4 5 6 7 8 9 | template<typename F> void Eval( const F& f ) { f(); } void foo() { Eval( []{ printf("Hello, Lambdas "); } ); } |
你好,兰姆达斯,第2版:
1 2 3 4 5 | void bar() { auto f = []{ printf("Hello, Lambdas "); }; f(); } |
我很难用lambda表达式来表达自己的想法,因为我在VisualFoxPro中工作,它有宏替换和execscript和evaluate()函数,它们的作用似乎大致相同。
1 2 3 4 5 | ? Calculator(10, 23,"a + b") ? Calculator(10, 23,"a - b"); FUNCTION Calculator(a, b, op) RETURN Evaluate(op) |
使用正式lambda的一个明显的好处是(我假设)编译时检查:在试图运行文本字符串之前,Fox不会知道您是否输入了上面的文本字符串。
这对于数据驱动的代码也很有用:您可以将整个例程存储在数据库的备注字段中,然后在运行时对它们进行评估。这允许您调整应用程序的一部分,而实际上不需要访问源。(但这完全是另一个话题。)
For a person without a comp-sci background, what is a lambda in the world of Computer Science?
我将用简单易读的python代码一步一步地直观地演示它。
简而言之,lambda只是一个匿名的内联函数。
让我们从作业开始,以基础算术为背景,了解一个大一新生的
分配蓝图为"名称=值",请参见:
1 2 3 4 5 6 | In [1]: x = 1 ...: y = 'value' In [2]: x Out[2]: 1 In [3]: y Out[3]: 'value' |
"x"、"y"是名称,"1"是值。试一试数学中的函数
1 2 | In [4]: m = n**2 + 2*n + 1 NameError: name 'n' is not defined |
错误报告,不能将数学直接写为代码,"n"应该被定义或赋值。
1 2 3 4 | In [8]: n = 3.14 In [9]: m = n**2 + 2*n + 1 In [10]: m Out[10]: 17.1396 |
它现在起作用了,如果你坚持把两条分离线组合成一条呢?有人来了。
1 2 3 | In [13]: j = lambda i: i**2 + 2*i + 1 In [14]: j Out[14]: <function __main__.<lambda>> |
未报告错误。
这是对
我们稍后再看。
让我们继续深入研究"作业"。
如上图所示,等号
试试这个:
1 2 3 4 5 | In [15]: x = print('This is a x') This is a x In [16]: x In [17]: x = input('Enter a x: ') Enter a x: x |
它适用于简单的语句,在Python7中有11种类型。简单语句-python 3.6.3文档
复合语句怎么样?
1 2 3 4 5 | In [18]: m = n**2 + 2*n + 1 if n > 0 SyntaxError: invalid syntax #or In [19]: m = n**2 + 2*n + 1, if n > 0 SyntaxError: invalid syntax |
出现了
1 2 3 4 5 6 | In [23]: def m(n): ...: if n > 0: ...: return n**2 + 2*n + 1 ...: In [24]: m(2) Out[24]: 9 |
tada,分析一下,"m"是名称,"n*2+2*n+1"是值。
现在返回到
尝试:
1 2 3 | In [28]: m = m(3) In [29]: m Out[29]: 16 |
这里有两个名称"m",函数
它的格式如下:
1 2 3 4 | In [27]: m = def m(n): ...: if n > 0: ...: return n**2 + 2*n + 1 SyntaxError: invalid syntax |
这不是一个明智的策略,所以错误报告
我们必须删除其中一个,设置一个没有名称的函数。
1 | m = lambda n:n**2 + 2*n + 1 |
它被称为"匿名函数"
总之,
希望,这有帮助。
在cs的上下文中,lambda函数是一个抽象的数学概念,它解决了数学表达式的符号评估问题。在这种情况下,lambda函数与lambda项相同。
但是在编程语言中,它是不同的。这是一段被宣布为"到位"的代码,可以作为"一流公民"传递。这个概念似乎很有用,所以它几乎可以应用到所有流行的现代编程语言中(参见lambda函数everwhere post)。
它是一个没有名称的函数。例如,在C中,您可以使用
1 | numberCollection.GetMatchingItems<int>(number => number > 5); |
返回大于5的数字。
1 | number => number > 5 |
这里是lambda部分吗?它表示一个接受参数(数字)并返回布尔值(数字>5)的函数。GetMatchingItems方法对集合中的所有项使用此lambda,并返回匹配项。
例如,在JavaScript中,函数被视为与其他所有函数相同的混合类型(
这是我正在玩的代码,看兔子洞有多深:
1 2 3 4 5 6 7 8 | 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]()()(); |
A
Lambda Function , or aSmall Anonymous Function , is a self-contained block of functionality that can be passed around and used in your code. Lambda has different names in different programming languages –Lambda in Python and Kotlin,Closure in Swift, orBlock in C and Objective-C. Although lambda's meaning is quite similar for these languages it has slight distinctions sometimes.
让我们看看lambda(closure)如何在swift 4.2中使用sorted()方法工作——从普通函数到最短表达式:
1 | let coffee: [String] = ["Cappuccino","Espresso","Latte","Ristretto"] |
1。正规函数
1 2 3 4 5 6 7 | func backward(_ n1: String, _ n2: String) -> Bool { return n1 > n2 } var reverseOrder = coffee.sorted(by: backward) // RESULT: ["Ristretto","Latte","Espresso","Cappuccino"] |
2。闭包表达式
1 2 3 | reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool in return n1 > n2 }) |
三。内联闭包表达式
1 | reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool in return n1 > n2 } ) |
4。从上下文推断类型
1 | reverseOrder = coffee.sorted(by: { n1, n2 in return n1 > n2 } ) |
5。从单个表达式闭包隐式返回
1 | reverseOrder = coffee.sorted(by: { n1, n2 in n1 > n2 } ) |
6。速记参数名称
1 2 3 | reverseOrder = coffee.sorted(by: { $0 > $1 } ) // $0 and $1 are closure’s first and second String arguments. |
7。操作员方法
1 2 3 | reverseOrder = coffee.sorted(by: >) // RESULT: ["Ristretto","Latte","Espresso","Cappuccino"] |
希望这有帮助。
我也明白了。我在JS上用过这个:
1 2 3 4 5 6 7 | var addAndMult = function(x) { return (function(y) { return (function(z) { return (x+y)*z; }); }); }; |
它增加2到4,然后将结果乘以6。但是我发现有时很难阅读:(
我还做了一个有趣的foreach函数:
1 2 3 4 5 6 7 | 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);
这个方法将迭代一个数组并执行一个操作——在这种情况下,打印到控制台。现在我也明白了为什么拉姆达是强大的。
在计算机编程中,lambda是一段代码(语句、表达式或它们的一组),它从外部源获取一些参数。它不能总是一个匿名函数——我们有很多方法来实现它们。
我们在表达式、语句和函数之间有明确的分离,这是数学家没有的。
编程中的"函数"一词也不同——我们有"函数是一系列要做的步骤"(从拉丁语"perform")。在数学中,它是关于变量之间的相关性。
函数语言试图尽可能地与数学公式相似,它们的单词含义几乎相同。但是在其他编程语言中,我们有不同的语言。
这个问题已经被完全回答了,我不想再详细讨论。我想分享一下在Rust中编写数值计算时的用法。
有一个lambda(匿名函数)示例
1 2 | let f = |x: f32| -> f32 { x * x - 2.0 }; let df = |x: f32| -> f32 { 2.0 * x }; |
当我写牛顿-拉斐逊方法的一个模块时,它被用作一阶和二阶导数。(如果您想知道什么是牛顿-拉斐逊方法,请访问"https://en.wikipedia.org/wiki/newton%27s_method"。
输出如下
1 2 3 | println!("f={:.6} df={:.6}", f(10.0), df(10.0)) f=98.000000 df=20.000000 |
想象一下,你有一家有送货选择的餐厅,你有一份订单需要在30分钟内完成。关键是客户通常不在乎你是骑自行车送食物还是赤脚送食物,只要你保持食物的温暖和捆绑。因此,让我们将这个习语转换为具有匿名和定义的传输函数的javascript。
下面我们定义了我们传递aka的方式,我们定义了一个函数的名称:
1 2 3 4 | // ES5 var food = function withBike(kebap, coke) { return (kebap + coke); }; |
如果我们使用arrow/lambda函数来完成这个传输,会怎么样?
1 2 | // ES6 const food = (kebap, coke) => { return kebap + coke }; |
你看,对客户来说没有区别,也没有浪费时间去思考如何发送食物。就寄吧。
顺便说一句,我不推荐带可乐的kebap,这就是为什么上面的代码会给你带来错误。玩得高兴。