浅析匿名函数、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>(, ); for_each(v->begin(), v->end(), show); return ;
}

若使用匿名函数是这样的:

 #include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std; int main() {
vector<int> * v = new vector<int>(, ); for_each(v->begin(), v->end(), [](int & v){
11 std::cout << "value " << v << std::endl;
12
}); return ;
}

  什么是捕获变量呢?就是让匿名函数可以使用匿名函数外定义的变量,但是匿名函数内的函数外变量是外部变量的一个clone(C++11可以捕获引用,不是clone。OC中有__block,也可以直接改变外部变量的值),在匿名函数内修改(诺能)外部变量不会影响到外部变量。可以说closure就是函数+捕获的变量。以lua为例:

 local intValue = ;

 local func = function (p)
intValue = intValue + p;
return intValue;
end print(func());
print(func());
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 = ; int (^blockFunc)(int p) = ^(int p) {
foo += p;
return foo;
}; NSLog(@"%d", blockFunc()); NSLog(@"%d", foo);
}
return ;
}  

  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,只能捕获克隆值,且不能改变他。

浅析匿名函数、lambda表达式、闭包(closure)区别与作用的更多相关文章

  1. 【Unity|C#】基础篇(9)——匿名函数 / Lambda表达式

    [学习资料] <C#图解教程>(第13章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu. ...

  2. 匿名函数 lambda表达式(lambda expression)

    阅读g2log时,发现有两行代码居然看不懂. 1. auto bg_call =  [this, log_directory]() {return pimpl_->backgroundChang ...

  3. (28)C#委托,匿名函数,lambda表达式,事件

    一.委托 委托是一种用于封装命名和匿名方法的引用类型. 把方法当参数,传给另一个方法(这么说好理解,但实际上方法不能当参数,传入的是委托类型),委托是一种引用类型,委托里包含很多方法的引用 创建的方法 ...

  4. Qt中使用匿名函数lambda表达式

    一.为什么要使用匿名函数lamdba 首先,lambda表达式可以使代码变得简单,C++中,一个lambda表达式表示一个可调用的代码单元.如代码: #include <QCoreApplica ...

  5. Python匿名函数——lambda表达式

    如果要定义的函数很简单,一个return语句就能搞定,可以使用lambda表达式来定义, lambda表达式的语法如下: lambda parameters: expression lambda表达式 ...

  6. python做中学(八)匿名函数lambda的用法

    匿名函数,顾名思义即没有名称的函数,和def定义的函数的最大区别在于匿名函数创建后返回函数本身(即匿名函数不需要return来返回值),表达式本身结果就是返回值,而def创建后则赋值给一个变量名,在P ...

  7. 匿名函数 =匿名方法+ lambda 表达式

    匿名函数的定义和用途 匿名函数是一个"内联"语句或表达式,可在需要委托类型的任何地方使用. 可以使用匿名函数来初始化命名委托[无需取名字的委托],或传递命名委托(而不是命名委托类型 ...

  8. 『Python基础-14』匿名函数 `lambda`

    匿名函数和关键字lambda 匿名函数就是没有名称的函数,也就是不再使用def语句定义的函数 在Python中,如果要声匿名函数,则需要使用lambda关键字 使用lambda声明的匿名函数能接收任何 ...

  9. 匿名函数(lambda)在列表生成式和生成器中的应用示例

    匿名函数(lambda)在列表生成式和生成器中的应用示例 列表生成式中实例 先看题: 以下代码的输出是什么?请给出答案并解释: def func(): return [lambda x: x * i ...

随机推荐

  1. 在 Linux 中使用 Git 及其 和 Eclipse 的集成

    ##参考资料## 我是通过阅读<Pro Git>这本书学习 Git 的,我读的时候还是第一版的英文版,现在已经出第二版了,而且英文版和中文版都有.英文第二版的地址是 [https://gi ...

  2. egret GUI 和 egret Wing 是我看到h5 最渣的设计

    一个抄袭FlexLite抄的连自己思想都没有,别人精髓都不懂的垃圾框架.也不学学MornUI,好歹有点自己想法. 先来个最小可用集合吧: 1. egret create legogame --type ...

  3. Html5 直接插入排序

    直接插入排序算法(Straight Insertion Sort),是排序算法中简单的一种算法,基本思想如下: 将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表.即:先将序列的第 ...

  4. My97DatePicker时间控件在项目中的应用

    一.下载My97DatePicker的压缩包My97DatePicker.rar,解压. 注:My97DatePicker最新版本有开发包,项目中使用时删掉,以便节省空间,提高程序的运行效率. 二.在 ...

  5. Android动画效果之Frame Animation(逐帧动画)

    前言: 上一篇介绍了Android的Tween Animation(补间动画) Android动画效果之Tween Animation(补间动画),今天来总结下Android的另外一种动画Frame ...

  6. How to debug .NET Core RC2 app with Visual Studio Code on Windows?

    Simone Chiaretta (http://codeclimber.net.nz/archive/2016/05/20/How-to-debug-NET-Core-RC2-app-with-Vi ...

  7. ASP.NET Core的配置(5):配置的同步[设计篇]

    本节所谓的"配置同步"主要体现在两个方面:其一,如何监控配置源并在其变化的时候自动加载其数据,其目的是让应用中通过Configuration对象承载的配置与配置源的数据同步:其二. ...

  8. 创建 Pool & VIP - 每天5分钟玩转 OpenStack(122)

    上节完成了 LBaaS 配置,今天我们开始实现如下 LBaaS 环境. 环境描述如下: 1. 创建一个 Pool “web servers”. 2. 两个 pool member “WEB1” 和 “ ...

  9. 集成学习之Adaboost算法原理小结

    在集成学习原理小结中,我们讲到了集成学习按照个体学习器之间是否存在依赖关系可以分为两类,第一个是个体学习器之间存在强依赖关系,另一类是个体学习器之间不存在强依赖关系.前者的代表算法就是是boostin ...

  10. h5应用缓存及收藏时Icon显示

    h5应用实现离线缓存,加载后,断网仍然可以继续使用. 一.需求 转行做h5,目前做赛道游戏,动手做了个赛道编辑器web版的,由于web版需要开启服务器才能使用,策划要想回家使用就要发布到外网服务器了, ...