由于函数是一种“第一类值”,因此一个显而易见的推论就是,函数不仅可以存储在全局变量中,还可以存储在table的字段和局部变量中。
大部分Lua库也采用了这种将函数存储在字段中的机制(io.read、math.sin).若要在Lua中创建这种函数,只需将常规的函数语法与table语法结合起来使用即可:
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
只要将一个函数存储到一个局部变量中,即得到了一个“局部函数”,也就是说该函数只能在某个特定的作用域中使用。
因为Lua是将每个程序块作为一个函数来处理的,所以在一个程序块中声明的函数就是局部函数,这些局部函数只在该程序块中可见。“词法域”确保了程序包中的其他函数可以使用这些局部函数:
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置于未定义的状态。
原文地址:http://my.oschina.net/u/223340/blog/294258