• 友链

  • 首页

  • 文章归档
h u a n b l o g
h u a n b l o g

欢

HI,Friend

04月
20
Lua

Lua闭包

发表于 2022-04-20 • 字数统计 2337 • 被 1,620 人看爆

函数是第一类值

function foo(x) return 2 * x end

--等价于
foo = function(x) return 2 * end

foo其实是一个变量,function(x)就是个匿名函数,没有名字

例如:使用table.sort进行排序,可以体现匿名函数的便利性

network = {
    {name = "grauna", IP = "210.26.30.34"},
    {name = "arraial", IP = "210.26.30.23"},
    {name = "lua", IP = "210.26.30.12"},
    {name = "derain", IP = "210.26.30.35"}
}

table.sort(network, function(a, b) return (a.name > b.name) end)

比如实现一个高阶函数,即导数: f'(x) = (f(x + d) - f(x)) / d

function derivatve(f, delta) 
    delta = delta or 1e-4
    return function(x) 
        return (f(x + delta) - f(x)) / delta
        end
end

c = derivatve(math.sin)
print(math.cos(5.2), c(5.2))        -->0.46851667130038     0.46856084325086
print(math.cos(10), c(10))          -->-0.83907152907645    -0.83904432662041

非全局函数

即局部函数,和局部变量一个原理
函数不仅可以储存在变量中,还可以存在表字段、表构造器和局部变量中

表字段

Lib = {}
Lib.foo = function(x, y) return x + y end
Lib.goo = function(x, y) return x - y end

print(Lib.foo(2, 3), Lib.goo(2, 3))             -->5	-1

表构造器

Lib = {
    foo = function(x, y) return x + y end,
    goo = function(x, y) return x - y end
}
Lib = {}

function Lib.foo(x, y) return x + y end
function Lib.goo(x, y) return x - y end

和声明变量一样,在函数前加上local,即可声明为局部函数

local function f(params)
    body
end

当定义为局部函数时,之前全局函数写法有些不适用

local fact = function(n)
    if n == 0 then return 1
    else return n * fact(n-1)       --调用不了,因为fact还未定义,要直到return后
    end
end

--解决办法将fact单独定义
local fact
fact = function(n)
    if n == 0 then return 1
    else return n * fact(n-1)       
    end
end

--或
local function fact(n)
    if n == 0 then return 1
    else return n * fact(n-1)       
    end
end

词法界定

function newCounter()
    local count = 0
    return function ()
        count = count + 1
        return count
    end
end

c1 = newCounter()
print(c1())     --> 1
print(c1())     --> 2
-- 其实调用的是newCounter里的匿名函数,count并未重新定义,count可以相当于另类的全局变量

闭包可以用来重定义函数,类似C#的(虚方法)

如:重定义函数sin以使其参数以角度为单位而不是以弧度为单位

local oldSin = math.sin
math.sin = function(x) 
    return oldSin(x * (math.pi / 180))
end

--或者 加上do-end   相当于作用域范围
do
    local oldSin = math.sin
    math.sin = function(x) 
        return oldSin(x * (math.pi / 180))
    end
end

--这样外面就不能访问oldSin
分享到:
Lua字符匹配
Lua流程控制和循环语句
  • 文章目录
  • 站点概览
欢

网红 欢

你能抓到我么?

Email RSS
看爆 Top5
  • mac系统版本与Xcode版本有冲突 4,080次看爆
  • JAVA_HOME环境配置问题 3,731次看爆
  • AssetBundle使用 3,499次看爆
  • VSCode配置C++开发环境 3,257次看爆
  • Lua反射 3,133次看爆

Copyright © 2025 欢 粤ICP备2020105803号-1

由 Halo 强力驱动 · Theme by Sagiri · 站点地图