首页 > 代码库 > Lua程序设计 非全局的函数

Lua程序设计 非全局的函数

         由于函数是一种“第一类值”,因此一个显而易见的推论就是,函数不仅可以存储在全局变量中,还可以存储在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置于未定义的状态。