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


    浅析匿名函数、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,只能捕获克隆值,且不能改变他。

  • 相关阅读:
    JVM简单入门
    10 张图聊聊线程的生命周期和常用 APIs
    Spring Cloud实战 | 最八篇:Spring Cloud +Spring Security OAuth2+ Axios前后端分离模式下无感刷新实现JWT续期
    ueditor 插入视频代码解析
    CentOS下添加新硬盘并分区格式化的详细步骤
    Java 8 stream
    crontab命令详解
    计算机网络自顶向下学习杂记
    nginx安装
    js识别PC和H5
  • 原文地址:https://www.cnblogs.com/BigFeng/p/5204899.html
Copyright © 2020-2023  润新知