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中我们也可以把函数名理解为 是一个变量。

 

 

 

作者:Miracle
来源:麦瑞克博客
链接:https://www.unitymake.com/archives/programming-life/lua/3448
本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0许可协议,转载请注明!
THE END
分享
打赏
海报
lua系统学习12-函数深入|Closure闭合|匿名函数|局部函数
Closure 闭合函数 table的排序方法就是用到了这种函数,匿名函数。 示例: names={"Miracle","Jack","xiaosha"} grades={Miracle=6,Jack=2,xiaosha=3} for……
<<上一篇
下一篇>>
文章目录
关闭
目 录