什么是lambda(函数)?

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

365317 次浏览

它引用lambda演算,这是一个只有lambda表达式的形式系统,它表示一个函数,该函数将函数作为其唯一参数并返回一个函数。lambda演算中的所有函数都是这种类型,即λ : λ → λ

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

(lambda (x y) (* x y))

它可以像这样在线应用(计算结果为50):

((lambda (x y) (* x y)) 5 10)

您可以将其视为一个匿名函数-这里有更多信息:维基百科-匿名函数

Lambda来自lambda演算,指编程中的匿名函数。

为什么这很酷?它允许您编写快速丢弃函数而无需命名它们。它还提供了一种编写闭包的好方法。有了这种能力,您可以做这样的事情。

python

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

正如你从Python的片段中看到的,函数加法器接受一个参数x,并返回一个匿名函数,或lambda,它接受另一个参数y。该匿名函数允许你从函数创建函数。这是一个简单的例子,但它应该传达lambda和闭包的强大功能。

其他语言的例子

perl5

sub adder {my ($x) = @_;return sub {my ($y) = @_;$x + $y}}
my $add5 = adder(5);print &$add5(1) == 6 ? "ok\n" : "not ok\n";

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

方案

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

C#3.5或更高

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

Swift

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

php

$a = 1;$b = 2;
$lambda = fn () => $a + $b;
echo $lambda();

haskell

(\x y -> 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 + yendendadd5 = adder(5)add5(1) == 6        -- true

静态编程语言

val pred = { x: Int -> x % 2 == 0 }val result = pred(4) // true

ruby

Ruby略有不同,因为您不能使用与调用函数完全相同的语法调用lambda,但它仍然具有lambda。

def adder(x)lambda { |y| x + y }endadd5 = adder(5)add5[1] == 6

Ruby就是Ruby,lambdas有一个简写,所以你可以这样定义adder

def adder(x)-> y { x + y }end

R

adder <- function(x) {function(y) x + y}add5 <- adder(5)add5(1)#> [1] 6

lambda是一种内联定义的函数类型。除了lambda,您通常还拥有某种变量类型,可以保存对函数、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中,我们得到了lambda,这使得代码更短:

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);}

它是一个没有名称的函数。例如,在c#中,您可以使用

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

返回大于5的数字。

number => number > 5

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

我喜欢这篇文章中对Lambdas的解释:LINQ的演变及其对C#设计的影响。它对我来说很有意义,因为它展示了Lambdas的真实世界,并将其作为一个实际示例构建出来。

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

稍微过于简化:lambda函数是可以传递给其他函数并且它的逻辑被访问的函数。

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

例如(在C#3中):

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

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

上面的语句变成了:

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

这与普通方法或匿名委托(实际上只是编译器魔术)不同,因为它们不能是阅读

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

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

现在表达式树不能被读取--不能分解某些ComplexCheck。SQL语句将在没有where的情况下执行,并且数据中的每一行都将通过SomeComplexCheck

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

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

这也有一个“内联”函数,但这一次它只是编译器的魔力-C#编译器将把它拆分为一个具有自动生成名称的新实例方法。

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

Ruby中的lambda示例如下:

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

将遗传以下输出:

HelloI am inside a proc

@Brian我一直在C#、LINQ和非LINQ运算符中使用lambdas。例子:

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

在C#之前,我在JavaScript中使用匿名函数来回调AJAX函数,甚至在Ajax这个术语被创造出来之前:

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

然而,C#的lambda语法的有趣之处在于,它们本身的类型不能被推断(即,您不能键入var foo=(x, y)=>x*y),但根据它们被分配到的类型,它们将被编译为代表表达式的委托或抽象语法树(这就是LINQ对象映射器如何发挥“语言集成”魔力)。

LISP中的Lambdas也可以传递给引用运算符,然后作为列表列表进行遍历。一些强大的宏就是这样制作的。

我很难理解lambda表达式,因为我在Visual FoxPro中工作,它具有宏替换以及ExecScript{}和Evalate()函数,它们似乎具有相同的目的。

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

使用正式lambdas的一个明确的好处是(我假设)编译时检查:Fox不会知道你是否输入了上面的文本字符串,直到它尝试运行它。

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

“lambda”这个名字只是一个历史产物。我们所谈论的只是一个值为函数的表达式。

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

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

其中foreach方法的参数是匿名函数的表达式。上面的行或多或少与编写这样的代码(不是真正的代码,但你会明白的)相同:

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

除了你不需要费心:

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

一旦你习惯了函数值,没有它们似乎就像被要求命名每个表达式一样愚蠢,比如:

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

而不是在你需要的地方写表达式:

println(2 * a + b)

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

例如,在JavaScript中,函数与其他所有函数(intstringfloatbool)被视为相同的混合类型。因此,你可以动态创建函数,将它们分配给事物,然后再调用它们。这很有用,但是,不是你想过度使用的东西,否则你会混淆所有必须在你…

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

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]()()();

仅仅因为我在这里看不到C++11的例子,我将继续从这里发布这个很好的例子。搜索后,这是我能找到的最清晰的语言特定示例。

你好,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();}

lambda演算是一种一致的代换数学理论。在学校数学中,例如x+y=5x−y=1配对。除了操纵单个方程的方法外,还可以将这两个方程的信息放在一起,前提是交叉方程的替换是在逻辑上完成的。Lambda演算编纂了进行这些替换的正确方法。

假设y = x−1是第二个等式的有效重排,这:λ y = x−1表示将符号x−1替换为符号y的函数。现在想象将λ y应用于第一个等式中的每个项。如果一个项是y,那么执行替换;否则什么都不做。如果你在纸上这样做,你将看到应用λ y将如何使第一个等式可解。

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

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

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

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

变量x是一个形式参数,它被实际值替换调用函数时要平方的值。在功能语言(方案)将定义相同的函数:

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

这在许多方面是不同的,但它仍然使用形式参数以同样的方式x。


添加:http://imgur.com/a/XBHub

lambda

在CS的上下文中,lambda函数是一个抽象的数学概念,它解决了数学表达式的符号求值问题。在这种情况下,lambda函数与lambda项相同。

但在编程语言中,它是不同的。它是一段被声明为“就位”的代码,可以作为“一等公民”传递。这个概念似乎很有用,以至于它出现在几乎所有流行的现代编程语言中(见lambda函数无处不在帖子)。

这个问题已经得到了正式的回答,所以我不会试图对此进行更多的补充。

简单地说,对于那些对数学或编程知之甚少或一无所知的人来说,我会把它解释为一个小“机器”或“盒子”,它接受一些输入,做一些工作并产生一些输出,没有特定的名称,但我们知道它在哪里,通过这些知识,我们使用它。

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

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

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

编程中的“函数”一词也不同-我们有“函数是一系列要做的步骤”(来自拉丁语“执行”)。在数学中,它是关于变量之间的相关性。

函数式语言试图尽可能地与数学公式相似,它们的单词意思几乎相同。但在其他编程语言中,我们有不同的。

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

我将用简单易读的python代码一步一步直观地说明它。

简而言之,lambda只是一个匿名的内联函数。

让我们从作业开始,作为一个有基本算术背景的新生来理解lambdas

赋值的蓝图是'名称=值',参见:

In [1]: x = 1...: y = 'value'In [2]: xOut[2]: 1In [3]: yOut[3]: 'value'

'x','y'是名称,1,'value'是值。尝试数学中的一个函数

In [4]: m = n**2 + 2*n + 1NameError: name 'n' is not defined

错误报告,
你不能直接将数学代码编写为代码,'n'应该被定义或分配给一个值。

In [8]: n = 3.14In [9]: m = n**2 + 2*n + 1In [10]: mOut[10]: 17.1396

它现在工作,如果你坚持将两个单独的行合并为一个。lambda

In [13]: j = lambda i: i**2 + 2*i + 1In [14]: jOut[14]: <function __main__.<lambda>>

没有错误报告。

这是对lambda的一瞥,它使您能够在一行中编写一个函数,就像您在数学中直接将其写入计算机一样。

我们稍后会看到它。

让我们继续深入挖掘“任务”。

如上所示,equals符号=适用于简单数据(1和“value”)类型和简单表达式(n**2+2*n+1)。

试试这个:

In [15]: x = print('This is a x')This is a xIn [16]: xIn [17]: x = input('Enter a x: ')Enter a x: x

它适用于简单的语句,在python7.简单语句-Python 3.6.3留档中有11种类型

复合语句怎么样,

In [18]: m = n**2 + 2*n + 1 if n > 0SyntaxError: invalid syntax#orIn [19]: m = n**2 + 2*n + 1, if n > 0SyntaxError: invalid syntax

这里有def使其工作

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'是值。:是'='的变体。
找到它,如果只是为了理解,一切都从赋值开始,一切都是赋值。

现在回到lambda,我们有一个名为'm'的函数

尝试:

In [28]: m = m(3)In [29]: mOut[29]: 16

这里有两个名称'm',函数m已经有一个名称,重复。

它的格式如下:

In [27]: m = def m(n):...:         if n > 0:...:             return n**2 + 2*n + 1SyntaxError: invalid syntax

这不是一个明智的策略,所以错误报告

我们必须删除其中一个,设置一个没有名称的函数。

m = lambda n:n**2 + 2*n + 1

它被称为“匿名函数”

总之,

  1. lambda在内联函数中,它使您能够像在数学中一样在一条直线上编写函数
  2. lambda匿名

希望,这有帮助。

这个问题已经完全回答了,我不想详细讨论。我想分享在Rust中编写数值计算时的用法。

有一个lambda(匿名函数)的例子

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”。

输出如下

println!("f={:.6}      df={:.6}", f(10.0), df(10.0))
f=98.000000       df=20.000000

想象一下,你有一家提供送餐选项的餐厅,你的订单需要在30分钟内完成。关键是客户通常不在乎你是骑车还是赤脚送食物,只要你保持食物的温暖和捆绑。所以让我们将这个习语转换为具有匿名和定义运输函数的Javascript。

下面我们定义了传递的方式,也就是我们为函数定义一个名称:

// ES5var food = function withBike(kebap, coke) {return (kebap + coke);};

如果我们使用箭头/lambda函数来完成这种传输会怎么样:

// ES6const food = (kebap, coke) => { return kebap + coke };

你看,对客户来说没有区别,也没有时间浪费在思考如何发送食物上。

顺便说一句,我不推荐可乐烤肉串,这就是为什么上面的代码会给你错误。玩得开心。

Lambda FunctionSmall Anonymous Function是一个自包含的功能块,可以在代码中传递和使用。Lambda在不同的编程语言中有不同的名称-python静态编程语言中的LambdaSwift中的Closure,或CObjective-c中的Block。尽管lambda的含义对于这些语言非常相似,但有时会有细微的区别。

让我们看看闭包(Lambda)在Swift中是如何工作的:

let coffee: [String] = ["Cappuccino", "Espresso", "Latte", "Ristretto"]

1.常规功能

func backward(_ n1: String, _ n2: String) -> Bool {return n1 > n2}var reverseOrder = coffee.sorted(by: backward)

// RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]

2.闭包表达式

reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool inreturn n1 > n2})

3.内联闭包表达式

reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool inreturn n1 > n2})

4.从上下文推断类型

reverseOrder = coffee.sorted(by: { n1, n2 in return n1 > n2 } )

5.单表达式闭包的隐式返回

reverseOrder = coffee.sorted(by: { n1, n2 in n1 > n2 } )

6.速记参数名称

reverseOrder = coffee.sorted(by: { $0 > $1 } )
// $0 and $1 are closure’s first and second String arguments.

7.运算符方法

reverseOrder = coffee.sorted(by: >)
// RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]

Lambda为大家讲解:

Lambda是一个匿名函数。这意味着lambda是Python中的一个函数对象,以前不需要引用。让我们考虑一下这里的这段代码:

def name_of_func():#command/instructionprint('hello')
print(type(name_of_func))   #the name of the function is a reference#the reference contains a function Object with command/instruction

为了证明我的命题,我打印出返回我们的name_of_func类型:

<class 'function'>

一个函数必须有一个接口,但是一个接口讲解员需要包含一些东西。这是什么意思?让我们仔细看看我们的函数,我们可能会注意到,在函数的名称中,有一些更多的细节我们需要解释才能理解什么是函数。

将使用语法"def"自定义参数定义一个常规函数,然后我们输入名称并用"()"解决接口,并用语法<前端>":"结束我们的定义。现在我们使用我们的指令/命令进入函数体。

所以让我们考虑一下这里的这段代码:

def print_my_argument(x):print(x)

print_my_argument('Hello')

在本例中,我们运行名为“print_my_argument”的函数并通过接口传递参数/参数。输出将是:

Hello

所以现在我们知道了什么是函数以及架构如何为函数工作,我们可以看看匿名函数。让我们考虑这里的这段代码:

def name_of_func():print('Hello')


lambda: print('Hello')

这些函数对象几乎相同,除了上面的常规函数有一个名称而另一个函数是匿名函数。让我们仔细看看我们的匿名函数,了解如何使用它。

所以让我们考虑一下这里的这段代码:

def delete_last_char(arg1=None):print(arg1[:-1])
string = 'Hello World'delete_last_char(string)
f = lambda arg1=None: print(arg1[:-1])f(string)

所以我们在上面的代码中所做的是再次编写一个常规函数和一个匿名函数。我们将匿名函数分配给一个var,这与给这个函数命名几乎相同。无论如何,输出将是:

Hello WorlHello Worl

为了充分证明lambda是一个函数对象,而不仅仅是模仿一个函数,我们在这里运行这段代码:

string = 'Hello World'f = lambda arg1=string: print(arg1[:-1])f()print(type(f))

输出将是:

Hello Worl<class 'function'>

最后但并非最不重要的是,你应该知道python中的每个函数都需要返回一些东西。如果函数体中没有定义任何内容,则默认情况下将返回无。看这里的这段代码:

def delete_last_char(arg1):print(arg1[:-1])
string = 'Hello World'x = delete_last_char(string)
f = lambda arg1=string: print(arg1[:-1])x2 = f()
print(x)print(x2)

输出将是:

Hello WorlHello WorlNoneNone

lambda函数可以接受任意数量的参数,但它们只包含一个表达式。…Lambda函数可用于返回函数对象。在语法上,lambda函数仅限于单个表达式。