闭包
首先,明确闭包的概念。个人理解,一个闭包是一个封闭的数据和状态集合,闭包在创建的时候,可以捕获包外的数据,然后在包内会有一个数据副本,闭包内数据的生命周期随着闭包的结束而结束。在lua中,闭包是以匿名函数的形式出现的,同时,lua中闭包的赋值是传递的引用。
给出一个代码的说明实例:
function foo(n)
local i = n
return function()
i = i + 1
return i
end
end
x1 = foo(0)
x11 = x1 -- 这里传递的是引用
x2 = foo(5)
print(x1())
print(x1())
print(x11())
print(x2())
print(x2())
结果输出:
1
2
3
6
7
从上述代码中,可以看到foo
函数返回一个闭包,这个闭包会捕获foo
内部变量i
的状态,一直到闭包的生命周期的结束。因此,闭包可以作为一个保存局部环境的方式。
迭代器
参考资料:https://www.lua.org/pil/7.1.html
假设我们想要借助闭包的方式遍历一个table,给出代码:
function list_iter(t)
local i = 0
local n = #t
return function()
i = i + 1
if i <= n then
return t[i]
end
end
end
t = {10, 20, 30}
iter = list_iter(t)
while true do
local elem = iter()
if elem == nil then
break
end
print(elem)
end
上述的代码还有更简洁的一个写法,即借助for
循环的方式,for
循环相当于泛型的迭代,它把迭代器保持在自己的内部,返回每次迭代的元素。当返回nil
时,终止迭代的流程。
function list_iter(t)
local i = 0
local n = #t
return function()
i = i + 1
if i <= n then
return t[i]
end
end
end
t = {10, 20, 30}
for elem in list_iter(t) do
print(elem)
end
但是,上述做法的缺陷在于每次新的循环,都要新建一个闭包,这会造成资源的浪费和消耗。