Lambda表达式

百度百科上讲:Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。

C++:

ISO C++ 11 标准的一大亮点是引入Lambda表达式。基本语法如下:

1

[capture list] (parameter list) -> return type { function body }

其中除了“[ ]”(其中捕获列表可以为空)和“复合语句”(相当于具名函数定义的函数体),其它都是可选的。它的类型是单一的具有成员operator()的非联合的类类型,称为闭包类型(closure type)。

C++中,一个lambda表达式表示一个可调用的代码单元。我们可以将其理解为一个未命名的内联函数。它与普通函数不同的是,lambda必须使用尾置返回来指定返回类型。

例如调用中的std::sort,ISO C++ 98 的写法是要先写一个compare函数:

1

2

3

4

bool compare(int& a,int& b)

{

    return a>b;

}

然后,再这样调用:

1

sort(a, a+n, compare);

然而,用ISO C++ 11 标准新增的Lambda表达式,可以这么写:

1

sort(a, a+n, [](int a,int b){return a>b;});//降序排序

这样一来,代码明显简洁多了。

由于Lambda的类型是单一的,不能通过类型名来显式声明对应的对象,但可以利用auto关键字和类型推导:

1

auto f=[](int a,int b){return a>b;};

和其它语言的一个较明显的区别是Lambda和C++的类型系统结合使用,如:

1

2

3

4

auto f=[x](int a,int b){return a>x;};//x被捕获复制

int x=0, y=1;

auto g=[&](int x){return ++y;};//y被捕获引用,调用g后会修改y,需要注意y的生存期

bool(*fp)(intint)=[](int a,int b){return a>b;};//不捕获时才可转换为函数指针

Lambda表达式可以嵌套使用。

ISO C++14支持基于类型推断的泛型lambda表达式。上面的排序代码可以这样写:

1

sort(a, a+n, [](const auto& a,const auto& b){return a>b;});//降序排序:不依赖a和b的具体类型

因为参数类型和函数模板参数一样可以被推导而无需和具体参数类型耦合,有利于重构代码;和使用auto声明变量的作用类似,它也允许避免书写过于复杂的参数类型。特别地,不需要显式指出参数类型使使用高阶函数变得更加容易。

lambda表达式有些部分是可以省略的,所以一个最简单的lambda表达式可以是下面这样,这段代码是可以通过编译的:

1

[] {}; // lambda expression

python:

Lambda表达式是Python中一类特殊的定义函数的形式,使用它可以定义一个匿名函数。与其它语言不同,Python的Lambda表达式的函数体只能有单独的一条语句,也就是返回值表达式语句。其语法如下: [2] 

lambda 形参列表 : 函数返回值表达式语句

下面是个Lambda表达式的例子:

1

2

3

4

#!/usr/bin/envpython

li=[{"age":20,"name":"def"},{"age":25,"name":"abc"},{"age":10,"name":"ghi"}]

li=sorted(li, key=lambda x:x["age"])

print(li)

如果不用Lambda表达式,而要写成常规的函数,那么需要这么写:

1

2

3

4

5

6

#!/usr/bin/envpython

def comp(x):

    return x["age"]

li=[{"age":20,"name":"def"},{"age":25,"name":"abc"},{"age":10,"name":"ghi"}]

li=sorted(li, key=comp)

print(li)

---------------------------------------------------------------------------------------------------------------------------------

Lambda语法格式
1、Lambda表达式的标准语法格式
Lambda表达式就是对函数式接口中抽象方法的实现,是对其匿名内部类的一个简写,只保留了方法的参数列表和方法体,其他的成分可以省略。因此,Lambda表达式的格式非常简洁,只有三部分组成:

参数列表

箭头

方法体

总结:(参数列表)->{方法体}

2、Lambda:省略模式
在Lambda标准格式的基础上,使用省略写法的规则为:

小括号内参数的参数类型可以省略。
小括号有且只有一个参数,则小括号可以直接省略。
如果大括号有且只有一个语句,无论是否有返回值,大括号、return关键字、分号可以省略。

---------------------------------------------------------------------------------------------------------------------------------

Java:

Java 8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁。当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口。下面这个例子就是使用Lambda语法来代替匿名的内部类,代码不仅简洁,而且还可读。

没有使用Lambda的老方法:

1

2

3

4

5

button.addActionListener(new ActionListener(){

    public void actionPerformed(ActionEvent actionEvent){

        System.out.println("Action detected");

    }

});

使用Lambda:

1

2

3

button.addActionListener( actionEvent -> { 

    System.out.println("Action detected");

});

让我们来看一个更明显的例子。

不采用Lambda的老方法:

1

2

3

4

5

6

Runnable runnable1=new Runnable(){

@Override

public void run(){

    System.out.println("Running without Lambda");

}

};

使用Lambda:

1

Runnable runnable2=()->System.out.println("Running from Lambda");

正如你所看到的,使用Lambda表达式不仅让代码变的简单、而且可读、最重要的是代码量也随之减少很多。然而,在某种程度上,这些功能在Scala等这些JVM语言里已经被广泛使用。

并不奇怪,Scala社区是难以置信的,因为许多Java 8里的内容看起来就像是从Scala里搬过来的。在某种程度上,Java 8的语法要比Scala的更详细但不是很清晰,但这并不能说明什么,如果可以,它可能会像Scala那样构建Lambda表达式。

一方面,如果Java继续围绕Lambda来发展和实现Scala都已经实现的功能,那么可能就不需要Scala了。另一方面,如果它只提供一些核心的功能,例如帮助匿名内部类,那么Scala和其他语言将会继续茁壮成长,并且有可能会凌驾于Java之上。其实这才是最好的结果,有竞争才有进步,其它语言继续发展和成长,并且无需担心是否会过时。

你可能感兴趣的:(c++,算法,开发语言,java)