浅析匿名函数、lambda表达式、闭包(closure)区别与作用
2016-02-21 14:35
615 查看
浅析匿名函数、lambda表达式、闭包(closure)区别与作用
所有的主流编程语言都对函数式编程有支持,比如c++11、python和java中有lambda表达式、lua和JavaScript中有闭包(closure)、ObjectC中有块(blocks,^)。那么这几个概念有什么共性和区别呢,只用普通函数不行吗,为什么要创造这些炫酷的概念呢?一.匿名函数、lambda、closure区别
从功能性上说lambda和closure(或是OC中的blocks)是一个东西,只是不同语言的不同称呼罢了,它们都是匿名函数。若匿名函数捕获了一个外部变量,那么它就是一个closure。二.匿名函数、lambda、closure作用
简单说,引入它们的作用有2个:简洁
捕获变量
首先说简洁,匿名函数可以在其他函数内部声明与定义,不用另外写个命名函数,举个栗子,显示c++vector中每个值,若不使用匿名函数,代码是这样的
#include <iostream> #include <vector> #include <algorithm> using namespace std; void show(int & value) { std::cout << "value " << value << std::endl; } int main() { vector<int> * v = new vector<int>(3, 1); for_each(v->begin(), v->end(), show); return 0; }
若使用匿名函数是这样的:
#include <iostream> #include <vector> #include <functional> #include <algorithm> using namespace std; int main() { vector<int> * v = new vector<int>(3, 1); for_each(v->begin(), v->end(), [](int & v){ 11 std::cout << "value " << v << std::endl; 12 }); return 0; }
什么是捕获变量呢?就是让匿名函数可以使用匿名函数外定义的变量,但是匿名函数内的函数外变量是外部变量的一个clone(C++11可以捕获引用,不是clone。OC中有__block,也可以直接改变外部变量的值),在匿名函数内修改(诺能)外部变量不会影响到外部变量。可以说closure就是函数+捕获的变量。以lua为例:
local intValue = 10; local func = function (p) intValue = intValue + p; return intValue; end print(func(3)); print(func(3)); print(intValue)
打印的结果为:13,16,10。可见匿名函数的外部变量被捕获到了func中。
三.匿名函数、lambda、closure在各个语言中的使用方式:
1.ObjectC:
在ObjectC中,匿名函数被称为blocks(块),即可以改变捕获的原值、又可以捕获克隆、但不能改变克隆值的值。捕获并改变外部值,需要用__block,否则复制语句会报错,使用代码如下:#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { __block int foo = 10; int (^blockFunc)(int p) = ^(int p) { foo += p; return foo; }; NSLog(@"%d", blockFunc(4)); NSLog(@"%d", foo); } return 0; }
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,只能捕获克隆值,且不能改变他。相关文章推荐
- 获取图片属性详细信息
- ttf文件属性详细信息
- SSH连接超时不自动断开
- 阿里云服务器加入现有域控的方法
- 阿里云服务器加入现有域控的方法
- 阿里云服务器加入现有域控的方法
- 阿里云服务器加入现有域控的方法
- HLS科普8 播放列表标签-媒体播放列表标签
- C++:重载运算符避免数组越界
- 利用CSS3实现图片切换特效
- 数据结构(9)--链队列的定义以及相关操作的实现
- ScreenCapturePro2 for Joomla_3.4.7-tinymce4x
- SpringMVC原理
- mybaties与hibernate的不同点
- 完美"mix-in"(混入)模式———js对象想怎么玩就怎么玩
- shell脚本远程查看服务器运行时间(不切换到远程服务器上)
- unity描边效果
- 获取手机联系人
- unity描边效果
- webservice 测试窗体只能用于来自本地计算机的请求