第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于后续版本,但有一些差异。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还将帮助支持 Lua 项目


6.2 – 非全局函数

一类函数的一个明显结果是我们不仅可以将函数存储在全局变量中,还可以存储在表字段和局部变量中。

我们已经看到表字段中函数的几个示例:大多数 Lua 库都使用此机制(例如,io.readmath.sin)。要在 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
    }
此外,Lua 还提供了另一种语法来定义此类函数
    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()   -- external local `f' is visible here
      ...
    end
Lua 使用语法糖支持此类局部函数
    local function f (...)
      ...
    end

递归局部函数的定义中出现了一个微妙的问题。朴素的方法在这里不起作用

    local fact = function (n)
      if n == 0 then return 1
      else return n*fact(n-1)   -- buggy
      end
    end
当 Lua 编译函数体中的调用 fact(n-1) 时,局部 fact 尚未定义。因此,该表达式调用全局 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 fact (n)
      if n == 0 then return 1
      else return n*fact(n-1)
      end
    end
当然,如果你有间接递归函数,这个技巧不起作用。在这种情况下,你必须使用显式前向声明的等效项
    local f, g    -- `forward' declarations
    
    function g ()
      ...  f() ...
    end
    
    function f ()
      ...  g() ...
    end