Lua中的闭包学习笔记

 更新时间:2014年12月10日 11:46:18   投稿:junjie  
这篇文章主要介绍了Lua中的闭包学习笔记,闭包是可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量),需要的朋友可以参考下

之前介绍 Lua 的数据类型时,也提到过,Lua 的函数是一种“第一类值(First-Class Value)”。它可以:

存储在变量或 table (例如模块面向对象的实现)里

复制代码 代码如下:

t = { p = print }
t.p("just a test!")

作为实参(也称其为“高阶函数(higher-order function)”)传递给其他函数调用

复制代码 代码如下:

t = {2, 3, 1, 5, 4}
table.sort(t, function(a, b) return (a > b) end)

作为其他函数的返回值

复制代码 代码如下:

function fun1(x) return fun2(x) end

函数在 Lua 里“第一类值”的特性,使它成为一种灵活,极具弹性的数据类型,同时,也让它衍生出一些特殊的功能强大的语言机制:

闭包(closure)

Lua 中的函数是带有词法作用域(lexical scoping)的第一类值,也可以说是函数变量的作用域,即函数的变量是有一定的效用范围的,变量只能在一定范围内可见或访问到。

例如如下代码:

复制代码 代码如下:

function count()
    local uv = 0
    local function retfun()
        uv = uv + 1
        print(uv)
    end
    return retfun
end

上面函数 retfun 定义在函数 count 里,这里可以把函数 retfun 看作是函数 count 的内嵌(inner)函数,函数 count 视为函数 retfun 的外包(enclosing)函数。内嵌函数能访问外包函数已创建的所有局部变量,这种特征就是上面所说的词法作用域,而这些局部变量(例如上面的变量 uv)则称为该内嵌函数的外部局部变量(external local variable)或 upvalue。

执行函数 count :

复制代码 代码如下:

c1 = count()
c1()            -- 输出 1
c1()            -- 输出 2

上面两次调用 c1,会看到分别输出 1 和 2。

对于一个函数 count 里的局部变量 uv,当执行完 "c1 = count()" 后,它的生命周期本该结束,但是因为它已成了内嵌函数 retfun 的外部局部变量 upvalue,返回的内嵌函数 retfun 以 upvalue 的方式把 uv 的值保存起来,因此可以正确把值打印出来。

这种局部变量在函数返回后会继续存在,并且返回的函数可以正常调用那个局部变量,独立执行其逻辑操作的现象,在 Lua 里称之为闭包(closure)

之所以说闭包是一个独立存在的个体,这个可以再把函数 count 赋给一个变量,然后执行看输出效果:

复制代码 代码如下:

c2 = count()
c2()                --  输出 1

c1 跟 c2 都是相同的函数体,不过输出的值却不一样!这主要还是因为闭包是由相应函数原型的引用和外部局部变量 upvalue 组成。当调用函数造成 upvalue 值被改变时,这只会改变对应闭包的 upvalue 值,不会影响到其他闭包里的 upvalue 值,所以 c1 被调用 2 次后,外部局部变量 uv 的值的是 2,而新创建的 c2 初始的外部局部变量 uv 是 0,被调用之后会是 1。

相关文章

  • Lua中使用table.concat连接大量字符串实例

    Lua中使用table.concat连接大量字符串实例

    这篇文章主要介绍了Lua中使用table.concat连接大量字符串实例,本文是Lua处理大量字符串的一个测试文章,测试了2种方法处理大量字符串的消耗时间,需要的朋友可以参考下
    2014-09-09
  • OpenResty中正则模式匹配的2种方法详解

    OpenResty中正则模式匹配的2种方法详解

    在 OpenResty 中,同时存在两套正则表达式规范:Lua 语言的规范和 Nginx 的规范,下面这篇文章主要给大家介绍了关于OpenResty中正则模式匹配的2种方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
    2018-04-04
  • Lua元表与元方法实例讲解

    Lua元表与元方法实例讲解

    这篇文章主要介绍了Lua元表与元方法实例讲解,本文讲解了算术类、关系类元方法、table访问的元方法等内容,需要的朋友可以参考下
    2014-09-09
  • Lua中使用table实现的其它5种数据结构

    Lua中使用table实现的其它5种数据结构

    这篇文章主要介绍了Lua中使用table实现的其它5种数据结构,本文用table为基础,实现了数组、链表、队列、集合等数据类型,需要的朋友可以参考下
    2014-09-09
  • Lua和C语言的交互详解

    Lua和C语言的交互详解

    这篇文章主要介绍了Lua和C语言的交互详解,Lua和C语言通过栈完成交互,本文结合代码实例详细讲解了交互的方法,需要的朋友可以参考下
    2014-09-09
  • Lua脚本实现递归删除一个文件夹

    Lua脚本实现递归删除一个文件夹

    这篇文章主要介绍了Lua脚本实现递归删除一个文件夹,本文给出了C++和Lua两个版本的实现代码,需要的朋友可以参考下
    2015-05-05
  • lua脚本语言快速入门教程

    lua脚本语言快速入门教程

    这篇文章主要介绍了lua脚本语言快速入门教程,本文讲解了变量及常量、字符串、逻辑控制语句、循环结构、函数及其使用等内容,需要的朋友可以参考下
    2015-03-03
  • Lua教程(十六):系统库(os库)

    Lua教程(十六):系统库(os库)

    这篇文章主要介绍了Lua教程(十六):系统库(os库)本文着重讲解了OS库中的日期和时间操作和其他系统调用两部份内容,需要的朋友可以参考下
    2015-04-04
  • Lua字符串模式匹配函数小结

    Lua字符串模式匹配函数小结

    这篇文章主要介绍了Lua字符串模式匹配函数小结,本文涉及一些正则操作,需要的朋友可以参考下
    2014-11-11
  • Lua教程(二):语法约定

    Lua教程(二):语法约定

    这篇文章主要介绍了Lua教程(二):语法约定,本文讲解了lua保留关键字、使用的标点符号、字符串、ASCII 码等,需要的朋友可以参考下
    2015-03-03

最新评论