函数是第一类值
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