|  | 
 
| 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))
运行输出:
 
 truefalse
 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())
运行输出:
 
 
 
 
 
 
 
 | 
 |