scala成长之路(7)函数进阶——可能是史上最浅显易懂的闭包教程
由于scala中函数内部能定义函数,且函数能作为函数的返回值,那么问题来了,当返回的函数使用了外层函数的局部变量时,会发生什么呢?没错,就产生是闭包。
关于闭包的解释网上一大堆,但基本上都是照葫芦画瓢,一个模子刻出来的,说来说去都只讲了“内部函数引用外层函数的局部变量”这个刻板的定义,根本没降到精髓。精髓是什么?且看我一句话给你讲清楚:
闭包就是外层函数函数的对象,外层函数就是闭包的构造函数!
怎么样,是不是摸不着头脑?其实是这样,我们使用闭包的目的并不是为了引用外层函数的局部变量,这只是手段,不是目的;我们的最终目的其实是函数的定制化,即按照一定的模板根据输出生成具有不同功能的函数,其实就是“函数的函数”。这里我们马上可以想到,就相当于“类”的思想,能根据不同的构造函数产生不同的“类的对象”。其实这里就是利用了这种思路,把外层函数当做构造函数,利用传入的参数进行定制,生成具有不同功能的函数并返回。
道理我都懂,但这跟“引用局部变量”有什么关系?很简单呀,比方说外层函数就是一个毛坯房,返回的函数时精装修房,那么外层函数的参数是装修图纸,最终得到的房子肯定是要用到这个图纸或者图纸的衍生物的,因此为了实现定制化,很定要依靠于外层函数的局部变量。
但是这里有个问题:我们都知道,正常来说函数的局部变量是存储在栈内存的,而对象是存储在堆内存的,因此同一个类可能存在多个对象,而函数在执行完成之后栈内存就会释放,因此不会存在多份函数的局部变量。但是根据我们上边的分析,定制化的函数肯定是要用到局部变量的,而且不同的定制化肯定是要保存多份局部变量,且相互之间空间独立的,就如同不同的对象一样。那么scala是怎么解决这个问题的呢?根据这篇文章 https://www.jianshu.com/p/8f24150fad2a 的介绍,scala在生成闭包时使用了一个临时对象来保存外层函数中的局部变量,因此可以算是将当前堆内存中的变量拷贝了一份到栈内存中,因此实现了多份局部空间的并存,以及函数闭包。
scala成长之路(7)函数进阶——可能是史上最浅显易懂的闭包教程的更多相关文章
- python成长之路七-函数的进阶
1,python中,名称空间分三种: 全局命名空间 局部命名空间(临时命名空间) 内置名称空间 2,作用域(两种): 1,全局作用域 包含:全局名称空间 内置名称空间 2,局部作用域 包含:局 ...
- scala成长之路(6)函数入门
众所周知,scala作为一门极客型的函数式编程语言,支持的特性包括: 函数拥有“一等公民”身份: 支持匿名函数(函数字面量) 支持高阶函数 支持闭包 部分应用函数 柯里化 首先需要指出,在scala中 ...
- scala成长之路(5)问题记录
还是在看scala sdk源码的时候,有很多问题要考自己慢慢摸索,这里做个记录. 一. 隐式转换的作用域? 隐式转换需要三个因素 1. 己方(当前对象) 2. 转换函数 3. 对方(转换的目标类) 这 ...
- scala成长之路(4)compaion object——伴生对象的使用
虽然java一直声称自己是完全面向对象的语言,但一直以来都被很多人所质疑,其中java的静态成员函数就是主要的“罪魁祸首”.由于java中保留了静态方法的调用,导致其编程模式依然有过程式编程的可能,尤 ...
- scala成长之路(3)隐式转换
不废话,先上例子:定义一个参数类型为String的函数: scala> def sayHello(name:String) = println("hello " + name ...
- scala成长之路(2)对象和类
scala提供了一种特殊的定义单例的方法:object关键字 scala> object Shabi{ | val age = 0 | val name = "shabi" ...
- scala成长之路(1)基本语法和数据类型
scala作为JVM上的Lisp,是一种geek类型的编程语言,也一直是我等java程序员眼中的梦寐以求的一门技能,遂下定决心花一段时间好好学习scala.第一天学习,主要介绍与java在编程上的主要 ...
- python成长之路六-函数的初识
定义函数 我们现学已知的python函数有<内置函数> 而我们现在要学的是<自定义函数> 1,def 定义一个函数 def name(): # 后接函数名 冒号 pass 2 ...
- Python之路----生成器函数进阶
def generator(): print(123) yield 1 print(456) yield 2 g = generator() ret = g.__next__() print('*** ...
随机推荐
- SharedPreferences的封装
android.content.SharedPreferences是一个接口,用来获取和修改持久化存储的数据.有三种获取系统中保存的持久化数据的方式: 1). public SharedPrefere ...
- Android 自定义View实现SegmentControlView(自定义多样式tablayout)
偷懒一下,不做过多阐述 参考资源: Android 自定义View实现SegmentControlView : https://blog.csdn.net/a512337862/article/det ...
- matlab练习程序(Arnold图像置乱)
自从上次写了Hilbert图像置乱之后,就对图像置乱研究了一下,发现这里面也是有很多置乱算法的. Arnold也算一种比较主要的置乱算法,算法由以下变换公式产生: 这里a和b是参数,n是迭代次数,N是 ...
- 一.配置简单的嵌入式tomcat和jetty
我们写了一个web应用,打成war包后,就需要找一个server来部署.对于我们的实际应用,我们基本没必要自己再写一个嵌入式的server.接下来两篇文章只是以钻研的心态来学习一下嵌入式tomcat和 ...
- when create a table,then show error ora-00952 tablespace tsb_1 not exist
QUESTION:When create a table,then show error ora-00952 tablespace tsb_1 not exist. STEP: 1.select us ...
- Struts2学习-拦截器2
1.做一个登陆页面(loginView.jsp,才用Action来访问),2.登陆成功后,可以跳转到系统的首页(index.jsp),3.首页有一个链接(testOtherAction访问其它的功能模 ...
- adb工具包使用方法
ADB工具包总共有四个文件,两个exe后缀,两个dll后缀.里面还带有fastboot.exe下载后在PC上安装,如安装到D:\adb_tools-2.0目录,确认目录中带有fastboot.exe文 ...
- 3.Zabbix 3.0 部署
请查看我的有道云笔记: http://note.youdao.com/noteshare?id=0139b8d2833129740be82e36a94e4fca&sub=5931260FCC8 ...
- 如何清理Windows缩略图缓存?
从Win95的IE4开始就有缩略图缓存了,缩略图缓存作用主要是用于存储Windows资源管理器缩略图图像文件.这加快了图像的显示速度,因为每次用户查看文件夹时都不需要重新生成这些较小的图像.缩略图缓存 ...
- 一个SAP开发人员的2017总结
今年的生活如此丰富多彩,不写一点什么怎么对得起这过去的一年? 就当记流水账,若干年之后回来看一定很有意思. 1月 有幸成为SAP Community上2位来自China的SAP mentor之一: 3 ...