|
upvalues 中文可以称之为外部局部变量,之所以称之为非局部,是因为当函数退出后,它仍然存在(正常情况下,局部变量会随着函数的退出也随之消失,因为函数栈也随之弹出),这说起来有点像 C 中的函数里的静态变量,却又不尽相同。
closures 中文可以称之为闭合函数。
下面用实例来讲解这两个概念。
考察下面代码:
- function MakeLessThan(N)
- return function(X)
- return X < N
- end
- end
- LessThanFive = MakeLessThan(5)
- LessThanTen = MakeLessThan(10)
- print (LessThanFive(4))
- print (LessThanFive(5))
- print (LessThanTen(5))
- print (LessThanFive(9))
- print (LessThanTen(9))
复制代码
运行输出:
true
false
true
false
true
分析:
注意,每一次调用 MakeLessThan() 函数时,都会创建一个新的局部变量 N 。按照一般情况,当 MakeLessThan() 返回时,局部变量应该也随之消失。然而,这里却不会这样!原因是,在 MakeLessThan() 里还有一个匿名函数要返回,这个匿名函数又会使用 MakeLessThan() 中的变量 N ,因此就不能使得 N 随着 MakeLessThan() 的退出而消失。
在 LessThanFive = MakeLessThan(5) 这条语句中,MakeLessThan() 将匿名函数返回到 LessThanFive 中。在后面的几条比较语句中,我们都可以看到 N 的持续存在。
当一个函数中的局部变量位于另一个范围(匿名函数)之上时,那么该变量称之为 “外部局部变量” 或 “upvalue” 。
一个函数含有一个或多个 upvalue 时,则称该函数为 “闭合函数” (closure)。
可以这么理解 upvalue 和 闭合函数:
一般来说,函数的局部变量会随着函数的退出而消失。但当该函数为闭合函数时,且当函数退出时,栈中的局部变量会被迁移到一个合适的地方保存起来。
再看另一个稍微特殊点的例子:- function MakeGetAndInc(N) -- 返回 N:
- local function Get()
- return N
- end
-
- -- N + M
- local function Inc(M)
- N = N + M
- end
-
- return Get, Inc
- end
- GetA, IncA = MakeGetAndInc(0)
- GetB, IncB = MakeGetAndInc(100)
- print (GetA())
- print (GetB())
- IncA(5)
- print (GetA())
- IncA(5)
- print (GetA())
- IncB(1)
- print (GetB())
- IncA(1)
- print(GetA())
复制代码
运行输出:
|
|