您的位置:首页 > 其它

浅析匿名函数、lambda表达式、闭包(closure)区别与作用

2016-07-18 17:38 1016 查看


浅析匿名函数、lambda表达式、闭包(closure)区别与作用

时间 2016-02-21 14:35:00  博客园-原创精华区
原文  http://www.cnblogs.com/BigFeng/p/5204899.html
主题 闭包 C++


浅析匿名函数、lambda表达式、闭包(closure)区别与作用

所有的主流编程语言都对函数式编程有支持,比如c++11、python和java中有lambda表达式、lua和JavaScript中有闭包(closure)、ObjectC中有块(blocks,^)。那么这几个概念有什么共性和区别呢,只用普通函数不行吗,为什么要创造这些炫酷的概念呢?


一.匿名函数、lambda、closure区别

从功能性上说lambda和closure(或是OC中的blocks)是一个东西,只是不同语言的不同称呼罢了,它们都是匿名函数。若匿名函数捕获了一个外部变量,那么它就是一个closure(闭包)。


二.匿名函数、lambda、closure作用

简单说,引入它们的作用有2个:
简洁
捕获变量

首先说 简洁 ,匿名函数可以在其他函数内部声明与定义,不用另外写个命名函数,举个栗子,显示c++vector中每个值,若不使用匿名函数,代码是这样的
1 #include <iostream>
2 #include <vector>
3 #include <algorithm>
4 using namespace std;
5
6 void show(int & value) {
7     std::cout << "value " << value << std::endl;
8 }
9
10 int main() {
11     vector<int> * v = new vector<int>(3, 1);
12
13     for_each(v->begin(), v->end(), show);
14
15     return 0;
16 }


若使用匿名函数是这样的:
1 #include <iostream>
2 #include <vector>
3 #include <functional>
4 #include <algorithm>
5 using namespace std;
6
7 int main() {
8     vector<int> * v = new vector<int>(3, 1);
9
10     for_each(v->begin(), v->end(), [](int & v){
11         std::cout << "value " << v << std::endl;
12     });
13
14     return 0;
15 }


什么是 捕获变量 呢?就是让匿名函数可以使用匿名函数外定义的变量,但是匿名函数内的函数外变量是外部变量的一个clone(C++11可以捕获引用,不是clone。OC中有__block,也可以直接改变外部变量的值),在匿名函数内修改(诺能)外部变量不会影响到外部变量。可以说closure就是函数+捕获的变量。以lua为例:
1 local intValue = 10;
2
3 local func = function (p)
4     intValue = intValue + p;
5     return intValue;
6 end
7
8 print(func(3));
9 print(func(3));
10 print(intValue)


打印的结果为:13,16,10。可见匿名函数的外部变量被捕获到了func中。


三.匿名函数、lambda、closure在各个语言中的使用方式:


1.ObjectC:

在ObjectC中,匿名函数被称为blocks(块), 即可以改变捕获的原值、又可以捕获克隆、但不能改变克隆值的值 。捕获并改变外部值,需要用__block,否则复制语句会报错,使用代码如下:
1 #import <Foundation/Foundation.h>
2
3 int main(int argc, const char * argv[]) {
4     @autoreleasepool {
5         __block int foo = 10;
6
7         int (^blockFunc)(int p) = ^(int p) {
8             foo += p;
9             return foo;
10         };
11
12         NSLog(@"%d", blockFunc(4));
13
14         NSLog(@"%d", foo);
15     }
16     return 0;
17 }  


2.C++:

C++中匿名函数被称为lambda, 即可以改变捕获的原值、又可以捕获克隆、又可以改变克隆值的值 ,语法形式可以简单归纳如下:

[capture](params)ops->ret{body;}

capture是捕获列表,params是参数表,opt是可选选项,ret是返回值类型,body是函数体。具体怎么使用可以参考 C++11
lambda 表达式解析 和 C++11
lambda 表达式。


3.lua:

lua中的匿名函数被称为闭包(closure), 只能捕获和改变原值的克隆,不能改变原值(table除外)


4.python:

python中的匿名函数被称为lambda, 只能捕获克隆值,且不能改变他。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息