浅析匿名函数、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. 如何让我们的PHP在Jexus中跑起来

    最近一段时间,经常看到不少的朋友在问,应该怎么设置才能够让Jexus支持PHP.其实,Jexus在很早之前就已经是可以支持PHP,像Apache或Nginx一样充当PHP的Web服务器的.不过由于没有 ...

  2. [译] 在Web API 2 中实现带JSON的Patch请求

    原文链接:The Patch Verb in Web API 2 with JSON 我想在.NET4.6 Web API 2 项目中使用Patch更新一个大对象中的某个字断,这才意识到我以前都没有用 ...

  3. ASP.NET MVC5+EF6+EasyUI 后台管理系统(33)-MVC 表单验证

    系列目录 注:本节阅读需要有MVC 自定义验证的基础,否则比较吃力 一直以来表单的验证都是不可或缺的,微软的东西还是做得比较人性化的,从webform到MVC,都做到了双向验证 单单的用js实现的前端 ...

  4. 构建高可用ZooKeeper集群

    ZooKeeper 是 Apache 的一个顶级项目,为分布式应用提供高效.高可用的分布式协调服务,提供了诸如数据发布/订阅.负载均衡.命名服务.分布式协调/通知和分布式锁等分布式基础服务.由于 Zo ...

  5. Chrome浏览器必装的扩展工具

    名称 作用 下载地址 Postman 模拟各种http请求 点击下载 JSON Viewer 访问json结果自动视图化 点击下载 Axure RP Extension for Chrome 查看Ax ...

  6. JavaScript 垃圾回收

    在公司经常会听到大牛们讨论时说道内存泄露神马的,每每都惊羡不已,最近精力主要用在了Web 开发上,读了一下<JavaScript高级程序设计>(书名很唬人,实际作者写的特别好,由浅入深)了 ...

  7. 阿里巴巴最新开源项目 - [HandyJSON] 在Swift中优雅地处理JSON

    项目名称:HandyJSON 项目地址:https://github.com/alibaba/handyjson 背景 JSON是移动端开发常用的应用层数据交换协议.最常见的场景便是,客户端向服务端发 ...

  8. 「译」JUnit 5 系列:架构体系

    原文地址:http://blog.codefx.org/design/architecture/junit-5-architecture/ 原文日期:29, Mar, 2016 译文首发:Linesh ...

  9. 手把手教从零开始在GitHub上使用Hexo搭建博客教程(三)-使用Travis自动部署Hexo(1)

    前言 前面两篇文章介绍了在github上使用hexo搭建博客的基本环境和hexo相关参数设置等. 基于目前,博客基本上是可以完美运行了. 但是,有一点是不太好,就是源码同步问题,如果在不同的电脑上写文 ...

  10. form表单的字符串进行utf-8编码

    <form>表单有assept-charset属性.该属性规定字符的编码方式,默认是"unknown",与文档的字符集相同. 该属性除了Internet explore ...