因为函数是一种“第一类值”,所以一个显而易见的推论就是,函数不只能够存储在全局变量中,还能够存储在table的字段和局部变量中。函数
大部分Lua库也采用了这种将函数存储在字段中的机制(io.read、math.sin).若要在Lua中建立这种函数,只需将常规的函数语法与table语法结合起来使用便可:lua
lib = {} lib.foo = function(x,y) return x + y end lib.goo = function(x,y) return x - y end 也可使用构造式: 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
只要将一个函数存储到一个局部变量中,即获得了一个“局部函数”,也就是说该函数只能在某个特定的做用域中使用。spa
由于Lua是将每一个程序块做为一个函数来处理的,因此在一个程序块中声明的函数就是局部函数,这些局部函数只在该程序块中可见。“词法域”确保了程序包中的其余函数可使用这些局部函数:code
local f = function(参数) <函数体> end local g = function(参数) <一些代码> f() -- f在这里是可见的。 <一些代码> end 对于这种局部函数的定义,Lua还支持一种“语法糖”: local function f(参数) <函数体> end 在定义递归的局部函数时,像下面这种函数的定义语法是错误的: local fact = function (n) if n == 0 then return 1 else return n*fact(n -1) end end 由于,当Lua编译到函数体中调用fact(n-1)的地方时,因为局部的fact还没有定义完毕,所以这句表达式实际上是调用一个全局的fact,而非此函数自身。 解决办法: local fact fact = function(n) if n == 0 then return 1 else return n*fact(n - 1) end end 如今函数中的fact调用就表示了局部变量。即便在函数定义时,这个局部变量的值还没有完成定义,但以后在函数执行时,fact则确定已经拥有了正确的值。
当Lua展开局部函数定义的“语法糖”时,并非使用基本函数定义语法。而是对于局部函数定义:递归
local function foo(参数) <函数体> end Lua将其展开为: local foo foo = function(参数) <函数体> end 使用这种语法来定义递归函数不会产生错误: local function fact(n) if n == 0 then return 1 else return n*fact(n - 1) end end 然而,在间接递归的状况中,必须使用一个明确的前向声明: local f, g --前向声明 function g () <一些代码> f() <一些代码> end function f () <一些代码> g() <一些代码> end 注意:别把第二个函数定义写为“local function f”.若是那样的话,Lua会建立一个全新的局部变量f,而将原来声明的f置于未定义的状态。