• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

lua中的闭包

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

1、在了解lua中的闭包之前,我们先来看一个栗子!!!

在上述例子当中,我们用lua的闭包实现了一个计数器。如果之前没有了解过闭包的概念的话,你一定会对上述代码的结果感到奇怪,下面我们就来详细的解释一下闭包。

2、第一类值(First class value )
lua中的函数就是所谓的”第一类值”。
在lua中定义一个函数就像创建普通类型值一样,lua中的函数就是一个值,它可以被存放在变量或数据结构中,可以被当做参数传给另一个函数,可以是另一个函数的返回值,还可以在运行期间被创建。
此外lua中的函数还可以嵌套定义,就是在函数里面定义函数,这也是lua闭包的基础。

3、词法定界
当一个函数内嵌套另一个函数的时候,内嵌套的函数可以访问外包函数的局部变量,这个特征就叫做词法定界。

4、闭包
表层理解闭包概念:
内嵌函数可以使用外包函数的局部变量,这种行为就叫做闭包。也就是词法定界。
深层理解闭包概念:
闭包=函数+upvalue。函数指的就是这些内嵌函数和外包函数。upvalue:内嵌函数可以访问外包函数已创建的所有局部变量,这些局部变量就被称为内嵌函数的upvalue。upvalue实际指的是变量而不是值,这些变量可以在内嵌函数之间共享,就好比C++类中的成员函数可以访问和修改成员变量一样。
可以看到,闭包实际上是数据和行为的结合体,就如同C++中的类一样,在某些情况下,我们需要记录某次调用完成以后数据的状态,就好比C++中的static变量一样,每次调用完成之后static类型的变量并不会被清除。
例:

在上述例子当中,upvalue实际上就是参数n,是一个局部变量。我们知道局部变量是保存在堆栈上的,只要upvalue不离开作用域,他就一直生存在函数堆栈上,这种情况下,闭包将使用指向堆栈上的upvalue的引用来访问他们。一但upvalue即将离开作用域,在从堆栈上消失之前,闭包将为upvalue分配新的空间并保存当前upvalue的值,以后便可通过新空间的引用来访问该upvalue。(如果用C语言来解释就是,通过指针访问upvalue这块空间的值,当离开作用域时,重新分配一块空间并将upvalue的值拷贝到里面,然后再让指针指向新分配的空间)
就如同上述例子一样,进入Increment之后闭包创建,这时n还没有离开作用域,所以还是使用堆栈上的n,当return之后离开作用域时,闭包会将n拷贝到自己管理的空间中。

5、闭包和函数的区别
实际上闭包只是在形式和表现上像函数,但实际上不是函数。
我们知道函数是是一些可执行的语句的组合体,这些代码语句在函数被定义后就确定了,并不会在执行时发生改变,所以函数只有一个实例。而闭包在运行时可以有多个实例,不同的upvalue和相同的函数组合可以产生不同的实例,就好像C++中相同的类代码可以创建不同的类实例一样。
例:下面实例和结果如图

lua编译一个函数时,其中包含了函数体对应的虚拟机指令、函数用到的常量值和一些调试信息。在运行时,lua每执行一个函数时,他就会创建一个一个新的数据对象,这个数据对象中包含了相应函数原型的引用、环境(用来查找全局变量的表)的引用以及一个由upvalue引用组成的数组,而这个数据对象就被称为闭包。由此可见,函数是编译期间的概念,是静态的,而闭包是运行期间的概念,是动态的。

6、闭包在迭代器中的应用
迭代器需要保留上一次调用的状态和下一次调用成功的状态,我们可以使用闭包机制来实现迭代器。
例:

结果:


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
vs2017编译Lua最新源码,生成动态链接库版本发布时间:2022-07-22
下一篇:
mac上安装lua发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap