博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
编程语言对lambda表达式的支持
阅读量:6994 次
发布时间:2019-06-27

本文共 5764 字,大约阅读时间需要 19 分钟。

Lambda表达式,也称为匿名函数,是一种无需定义名称的函数或子程序,在很多高级语言中普遍存在。1958年LISP首先采用匿名函数,发展至今,越来越多的语言开始支持该特性,包括C++, PHP等,本文列举了常用的编程语言对lambda表达式的支持,增强对lambda表达式的认识,并了解不同是如何支持lambda表达式的。

Java 8

2013年Java 8的发布,宣布java对lambda表达式的支持,在java支持lambda表达式之前,我们必须这样写代码:

1
2
3
4
5
button.addActionListener(
new
ActionListener() {
    
public
void
actionPerformed(ActionEvent e) {
        
ui.dazzle(e.getModifiers());
    
}
});

你还需要导入java.awt.event.ActionListener功能接口。而java8带来了lambda表达式,我们只需这样写:

1
button.addActionListener(e -> { ui.dazzle(e.getModifiers()); });

编译器知道lambda表达式符合void actionPerformed(ActionEvent)方法的定义,看起来lambda实体返回的是void,实际上编译器能推断出参数e的类型就是java.awt.event.ActionEvent。

java 8的lambda表达式的出现主要是大大简化了功能接口的编写,同时java8还提供了java.util.functions包,包含了很多新的功能接口和迭代方法,这些功能都分成类似于LINQ。

C++ 11

c++ 11也开始支持labmda表达式来,C++ 11的lambda表达式的格式如下:

1
[capture](parameters) mutable or exception->
return
-type {body}

[capture]表示一个Lambda表达式的开始,这部分是必须的,不能省略。capture是传递给编译器自动生成的函数对象类的构造函数,capture只能使用那些定义当前lambda表达式之前所定义的,并且在lambda作用范围内可见的局部变量(包含lambda所在类的this),包含以下形式:

空, 不使用该参数;=。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。&。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)。this。函数体内可以使用Lambda所在类中的成员变量。a。将a按值进行传递。按值进行传递时,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的。要修改传递进来的a的拷贝,可以添加mutable修饰符。&a。将a按引用进行传递。a, &b。将a按值进行传递,b按引用进行传递。=,&a, &b。除a和b按引用进行传递外,其他参数都按值进行传递。&, a, b。除a和b按值进行传递外,其他参数都按引用进行传递。

parameters表示重载的()操作符参数,没有参数时,可以省略。参数可以按值(如:(a, b)),也可以按引用(如:(&a, &b))传递参数。

mutalbe或exception声明可以省略,按值传递[capture]参数时,加上mutalbe修饰符,可以修改参数拷贝的值(修改的是值类型的拷贝)。exception声明用于指定函数抛出的异常,如抛出整数类型的异常:throw(int)。

“-> return-type”,表示函数返回值类型,当没有返回值时,或者函数体内只有一处return语句(编译器可以推断出返回值的类型),该部分就可以省略。

{body}表示函数的实现,函数体可以空,当花括号不能省略。

看一个例子,该例子是统计字符串中的大写字母,使用for_each遍历字符串,使用lambda表达式检查字母是否为大写,如果是大学,uppercase加1:

1
2
3
4
5
6
7
8
9
int
main()
{
    
char
s[]=
"Hello World!"
;
    
int
uppercase =
0
;
//modified by the lambda
    
for_each(s, s+sizeof(s), [&uppercase] (
char
c) {
        
if
(isupper(c))
             
uppercase++;
    
});
    
cout<< Uppercase<<
" uppercase letters in: "
<< s<

uppercase是定义在lambda表达式外的一个变量,并且声明在lambda表达式之前,[&uppercase]中的“&”表示lambda函数体中使用的uppercase为一个应用类型,以便更新大写字母的个数。

Objective-C

下面的例子,分别是Objective-C和C++ 11的Lambda表达式写法:

1
^{ printf(
"Hello, World!\n"
); } ();
1
[] { cout <<
"Hello, World"
<< endl; } ();

在创建Objective-C的lambda表达式时,在语法上是以“^”开始,而C++ 11是以“[]”开始。

实际上Objective-C的lambda表达式是构建在C语言之上的,也称为block,是C语言的扩展特性,如果你理解C语言的函数指针,那么有很容易理解Objective-C的block了,只是语法稍微不同。如下一个block的原型:

1
int
(^maxBlk)(
int
,
int
);

除了“^”外,是不是和C语言的函数指针的声明一样。上面的示例就是声明一个block原型,名字为maxBlk,带有两个个int参数,返回值为int类型。

Objective-C有了Lambda表达式后,就可以很容易的定义一个满足maxBlk签名的函数,并且这个函数是匿名的。如下:

1
maxBlk = ^(
int
m,
int
n){
return
m > n ? m : n; };

你也可以这样写:

1
int
(^maxBlk)(
int
,
int
) = ^(
int
m,
int
n){
return
m > n ? m : n; };

看如下Objective-C的代码,包含了3给block:

1
2
3
4
5
6
7
8
9
10
11
12
#
import
int
(^maxBlk)(
int
,
int
) = ^(
int
m,
int
n){
return
m > n ? m : n; };
 
int
main(
int
argc,
const
char
* argv[])
{
    
^{ printf(
"Hello, World!\n"
); } ();
 
    
int
i =
1024
;
    
void
(^blk)(
void
) = ^{ printf(
"%d\n"
, i); };
    
blk();
    
return
0
;
}

C#

C#早在2.0版本就引入了匿名方法,简化了我们编写事件处理函数的工作,使我们不再需要单独声明一个函数来绑定事件,只需要delegate关键字就可以编写事件处理代码了。如下:

1
2
3
4
// Create a handler for a click event
button1.Click += delegate(System.Object o, System.EventArgs e) {
    
System.Windows.Forms.MessageBox.Show(
"Click!"
);
};

而C#3.0再更进一步地推出了Lambda表达式,使得编写事件处理函数更加简洁,lambda表达式更新一个计算表达式,使用“=>”符合来连接事件参数和事件处理代码。如:

1
button1.Click += (o, e) => { System.Windows.Forms.MessageBox.Show(
"Click!"
); };

在C#中,事件处理函数其实就是委托。委托除了可以作为事件处理函数,还可以作为函数指针,或回调函数使用,都可以使用lambda表达式的写法。如:

1
2
3
delegate
int
del(
int
i);
del myDelegate = x => x * x;
int
j = myDelegate(
5
);
//j = 25

或者:

1
2
Func myFunc = x => x ==
5
;
bool result = myFunc(
4
);
// returns false of cour

另外Lambda表达式在LINQ中发挥了重要作用。

PHP 5.3

PHP5.3增加了Lambda的支持,对于接受回调函数的PHP函数来说,lambda表达式非常方便。比如使用array_map函数遍历数组,并将回调结果重新赋值给数字各元素。在早期PHP版本中,我们在调用array_map之前,必须事先定义好回调函数,比如:

1
2
3
4
5
6
7
8
9
function quoteWords()
{
     
if
(!function_exists (
'quoteWordsHelper'
)) {
         
function quoteWordsHelper($string) {
             
return
preg_replace(
'/(\w)/'
,
'"$1"'
,$string);
         
}
      
}
      
return
array_map(
'quoteWordsHelper'
, $text);
}

现在PHP5.3对lambda表达式的支持,使得编码根据简单。如下使用lambda表达式的实现:

1
2
3
4
5
6
7
function quoteWords()
{
     
return
array_map(
'quoteWordsHelper'
,
            
function ($string) {
                
return
preg_replace(
'/(\w)/'
,
'"$1"'
,$string);
            
});
}

Python

Python世界的lambda表达式根据简单,只是在python世界里,lambda表达式主要适用比较小的函数。如普通Python的函数定义:

1
2
3
def func(x):
    
return
x *
2
func(
2
) #
4

使用lambda表达式的写法:

1
2
func = lambda x:x*
2
func(
2
) #
4

python的lambda表达式常用在一些回调中,比如:

1
2
a = [
1
,
2
,
3
,
4
]
map(lambda x:x**
2
, a) # output: [
1
,
4
,
9
,
16
]

或者

1
2
3
a = [
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
]
low, high =
3
,
7
filter(lambda x:high>x>low, a) # output: [
4
,
5
,
6
]

"x**2"表示x的平方。"high>x>low"等于“high>x and x > low”。

Javascript

javascript中的lambda表达式通常称为匿名函数,如果你使用过jquery库,那么你肯定知道匿名函数,这里主要作为回调函数使用。比如:

1
$(
'#submit'
).on(
'click'
, function(){ functionbody. })

其中方法on的第二个参数就是匿名函数,javascript中的你们函数还有其他存在形式,比如:

1
var func =
new
Function(
'x'
,
'return 2*x;'
);

或者

1
var func = function(x) {
return
2
*x; }

还有就是很多js库常用的方式,表示创建匿名函数,并调用之:

1
2
3
(function(x, y) {
    
alert(x+y);
})(
2
,
3
);

总结

lambda表达式的出现简化了编码量,多用于函数回调、事件、匿名函数,并且与闭包的结合使用,更能发挥强大的作用。另外,支持lambda表达式的编程语言有很多,这里主要介绍了我相对熟悉的几种。

参考

http://datumedge.blogspot.co.uk/2012/06/java-8-lambdas.htmlhttp://www.softwarequalityconnection.com/2011/06/the-biggest-changes-in-c11-and-why-you-should-care/http://www.cnblogs.com/hujian/archive/2012/02/14/2350306.htmlhttp://msdn.microsoft.com/zh-cn/LIBRARY/bb397687(v=vs.90).xhttp://php.net/manual/zh/migration53.new-features.phphttp://my.oschina.net/u/574366/blog/146422http://www.xs-labs.com/en/archives/articles/objc-blocks/ 版权所有,转载请注明出处:http://guangboo.org/2014/01/16/lambda-supported-programming-language

你可能感兴趣的文章
array_kes($array,search,type) 的妙用
查看>>
《Asp.Net Web API》 ----路由机制
查看>>
Spring Boot 学习例子
查看>>
js this
查看>>
mvc view 中 js 不反应
查看>>
高级特性(8)- JavaBean构件
查看>>
20. Cookie 和 Session
查看>>
linux学习摘记
查看>>
C++11之function模板和bind函数适配器
查看>>
mac地址,厂商对应列表
查看>>
VUE3)操作cookie
查看>>
python 文件处理总结
查看>>
jmeter和loadrunner测试结果差异大-web页面静态资源下载
查看>>
一个长期颈椎问题的工薪阶层关于颈椎的康复和预防的心得
查看>>
jsp中${pageContext.request.contextPath}的意思
查看>>
搭建Android开发环境
查看>>
iOS开发 引用第三方库出现duplicate symbol时的处理方法
查看>>
解放iOS&Android程序猿:Testin云测试破1000万次
查看>>
npm常用命令
查看>>
第十二章:二叉查找树(3)
查看>>