- 对于习惯了C/C++这种不可嵌套定义的语言的同学来说,理解闭包真不太容易。Lua定义函数就象创建普通类型值一样,在函数体中仍然可以定义函数。
-
-
Lua 中的函数是带有词法定界(lexical scoping)的第一类值(first-class values)。
-
-
首先注释几个概念
-
-
第一类值(first-class values)指: 一个对象(广义概念上)在运行期间被创建,可以当做一个参数被传递,从子函数返回或者可以被赋给一个变量。
-
http://en.wikipedia.org/wiki/First-class_object
-
wiki里面定义一个object是first-class要具备如下几个特征
-
可以被存放在变量和数据结构中
-
可以当做参数传递给子过程
-
可以当子过程的返回值
-
可以在运行期间被创建
-
具备内在等同性(独立于给定的名字)// 不太理解这个
-
-
C语言里面函数不能在运行期被创建,因此不是第一类值,不过有时他们被称为第二类值,原因是他们可以通过函数指针实现某些特性,比如常常显现的回调函数的影子。
-
-
Lua里面函数可以存放在变量中,也可以存放在表(table)中,可以作为函数的参数,还可以作为函数的返回值。所以Lua里面的函数是第一类值.
-
-
Non-local variable :不是在局部作用范围内定义的一个变量,但又不是一个全局变量。主要应用在嵌套函数和匿名函数里。
-
在Python(3.x),用于在嵌套函数中访问外部变量
-
-
def outer():
-
x = 1
-
def inner():
-
nonlocal x #使用nonlocal引用外部函数变量
-
x += 1
-
print(x)
-
return inner
-
-
若没有nonlocal则x被看成是inner的局部变量而不认为是outer内的那个变量,因此只是一个与外部同名的未赋值过的变量,没法进行加1运算。
-
-
词法定界:是一个静态域概念,用来关联一个标识符和它的值,一个标识符的绑定只与程序语句的组织有关,而与程序运行时无关。变量只在其定义的block中可见,离开此block变量就不存在了。
-
http://en.wikipedia.org/wiki/Scope_(programming)#Lexical_scoping
-
-
相应有动态域概念:Dynamic Scoping无法在编译时确定变量的绑定,需要在程序的运行过程中才能确定。
-
在运行过程中,每个变量都有一个对应的stack来保存绑定。应用动态域不适合编写模块化程序,
-
-
upvalue:内嵌函数可以访问外包函数已经创建的所有局部变量,这些局部变量称为该内嵌函数的外部局部变量(external local variable)或者upvalue,upvalue实际指的是变量而不是值。这些变量可以在内部函数之间共享:比如 n是函数ia和ib的upvalue
-
function ab(n)
-
function ia()
-
print(n)
-
end
-
function ib()
-
n = n + 1
-
end
-
return ia,ib
-
end
-
-
a,b=ab(5)
-
-
a()-->5
-
b()
-
a()-->6 //b() 对n执行了+1 操作,
-
-
简单的说闭包是一个函数加上它可以正确访问的 upvalue。upvalue是嵌套函数的外部函数的局部变量。
- 这个函数一般定义在另一个函数内部;他可以访问定义在外部函数内的成员变量,参数,以及全局函数。并且这个函数还可以返回函数。