lua系统学习12-函数深入|Closure闭合|匿名函数|局部函数
Closure 闭合函数
table的排序方法就是用到了这种函数,匿名函数。
示例:
names={"Miracle","Jack","xiaosha"}
grades={Miracle=6,Jack=2,xiaosha=3}
for i,v in ipairs(names) do
print(i,v)
end
t=table.sort(names,function(name1,name2)
return grades[name1]<grades[name2]
end)
for i,v in ipairs(names) do
print(i,v)
end
1 Miracle
2 Jack
3 xiaosha
1 Jack
2 xiaosha
3 Miracle
table.sort 需要两个参数{arg1=要排序的列表,arg2=一个返回值为boolean的函数 }
上面示例中使用了匿名函数,直接写在了参数列表内部。
table.sort内部会调用这个函数,根据函数的返回值来判断前一个和后一个的值 要大于还是要小于的条件进行排序。
它总是以返回值结果为false作为去对换前后者的依据。那么概况意思就是说我想要让所有后者都大于前者,就是从小到大排序。
以上面示例来看,grades[name1]<grades[name2]
name1是前者 name2是后者 每次会向后迭代 下一次判断就是name2 与name3
我们通过grades的构造可以知道name1>name2
grades[name1]<grades[name2]=false 故需要对换。
在上面案例中,我们还发现这样的匿名函数竟然可以取得grades。这是函数本身就是写在grades主体下的,且直接取得地址,后面即使主体的域结束,该函数依然可以保存对grades的引用。
function Func2()
local localVariable;
if not localVariable then
localVariable=0;
end
return function() localVariable=localVariable+1 return localVariable end
end
varFunc=Func2()
print(varFunc())
print(varFunc())
print(varFunc())
输出
1
2
3
function Func2()
local localVariable;
if not localVariable then
localVariable=0;
end
return function() localVariable=localVariable+1 return localVariable end
end
varFunc=Func2()
print(varFunc())
print(varFunc())
print(varFunc())
varFunc=Func2()
print(varFunc())
print(varFunc())
print(varFunc())
输出
1
2
3
1
2
3
通过上面两个测试 我们发现 这里的i在匿名函数中并不是局部变量也不是全局变量,我们叫他非局部变量。它每次都会续上一次调用结束后的i;但是下一次调用了Func2 它又从头开始了。
说明i在func2是局部函数,会随域结束被销毁。但在匿名函数中又把这个属于func2的局部函数存在Closure的栈中,这样虽然在func2结束了销毁对func2的引用,但是Closure中还有对i的引用。
那么什么是Closure呢,所谓Closure就是该函数和它所需要的所有非局部变量。
简单地讲就是一个closure就是一个函数加上该函数所需访问的所有非局部变量。如果再次调用Func2,那么就会创建一个新的局部变量i,从而得到一个新的closure。
引用Lua程序设计第二版内容
函数覆盖
function funcName()
dofile("C:\\File\\Lua\\Closure2.lua")
print(notLocalVar())
print(notLocalVar())
end
funcName()
funcName=function() print( "test") end
funcName()
HelloWorld
1
2
test
通过这种方法与Closure,Lua还可以构建一个安全的环境;
用非局部变量暂存原有方法,而使用匿名函数重构覆盖原有方法,在原有函数中设置受限条件,只有符合条件去访问这个非局部变量调用原有的方法。看代码
非全局的函数
函数不仅可以存储在全局变量中,还可以存储在table的字段中和局部变量中。**只要将一个函数存储到一个局部变量中,即得到了一个局部函数 也就说该函数只能在某个特定的作用域中使用。
简单来说就是在一个程序块(Chunk)**中定义的函数就是局部函数
使用Table来存放函数的几种方法
function tableSaveFunc()
function tableSaveFuncMethod1()
t={}
t.a=function(name,description) return "名字","描述" end
t.b=function(arg,sex) return "年龄","性别" end
print(t.a())
print(t.b())
end
tableSaveFuncMethod1()
function tableSaveFuncMethod2()
t={}
function t.a(name,description) return "名字","描述" end
function t.b(arg,sex) return "年龄","性别" end
print(t.a())
print(t.b())
end
tableSaveFuncMethod2()
function tableSaveFuncMethod3()
t={a=function(name,description) return "名字","描述" end,b=function(arg,sex) return "年龄","性别" end}
print(t.a())
print(t.b())
end
tableSaveFuncMethod3()
end
tableSaveFunc()
可以看到tableSaveFuncMethod2这个方法有点特殊。
它是直接在定义函数时候 指定列表索引变量作为函数地址的存放位置。
当然局部函数可以显示的去定义
function localFunc()
local f=function()
print(1,2,3)
end
function gg()
f() end
gg()
f()
end
localFunc();
1 2 3
1 2 3
虽然局部函数可以显式的去定义,但是我觉得没必要,因为局部函数与局部变量还有点不同,变量在方法中如果没定义local 他就是全局的,但是函数的话,如果一个函数在块中,lua会自动把这个函数判定为局部函数。所以这么看显式得定义局部函数 就显得有点多余了。
除此之外局部函数的定义还可以这样写
local function aaa()
end
在使用一个局部变量去初始化接收一个函数的时候,可能会发生一个问题。
function localVariableRefFunc()
local f=function(n)
if n==0 then
return 1
else
return n*f(n-1)
end
end
print(f())
end
localVariableRefFunc()
在上面这个示例中,编译器发生了报错,具体原因是因为 在等号赋值符右侧的表达式优先去计算,最后才会计算等号左边的。
也就是说 当我们函数中用到了f的时候,其实局部变量f还没有初始化,还没有去接收当前这个函数,可以说还不存在局部f,就引用了F。那么我们在函数中使用的这个f其实被lua自动引用的是一个全局变量f的地址 值为nil。
修改之后,先定义局部变量f,这样f存在于局部域中。
function localVariableRefFunc()
local f=nil
f=function(n)
if n==0 then
return 1
else
return n*f(n-1)
end
end
print(f(10))
end
localVariableRefFunc()
当然 我们还知道局部函数另外一种定义
function localVariableRefFunc()
local function f(n)
if n==0 then
return 1
else
return n*f(n-1)
end
end
print(f(10))
end
localVariableRefFunc()
所以我们在lua中我们也可以把函数名理解为 是一个变量。
来源:麦瑞克博客
链接:https://www.playcreator.cn/archives/programming-life/lua/3448/
本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0许可协议,转载请注明!