第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于更高版本,但有一些区别。
第四版针对 Lua 5.3,可在 Amazon 和其他书店购买。
购买本书,您还可以帮助支持 Lua 项目


5 – 函数

函数是 Lua 中抽象语句和表达式的主要机制。函数既可以执行特定任务(在其他语言中有时称为过程子例程),也可以计算并返回值。在第一种情况下,我们将函数调用用作语句;在第二种情况下,我们将它用作表达式

    print(8*9, 9/8)
    a = math.sin(3) + math.cos(10)
    print(os.date())
在这两种情况下,我们都会编写一个用括号括起来的参数列表。如果函数调用没有参数,我们必须编写一个空列表 () 来指示调用。此规则有一个特例:如果函数只有一个参数,并且此参数是文字字符串或表构造函数,则括号是可选的
    print "Hello World"     <-->     print("Hello World")
    dofile 'a.lua'          <-->     dofile ('a.lua')
    print [[a multi-line    <-->     print([[a multi-line
     message]]                        message]])
    f{x=10, y=20}           <-->     f({x=10, y=20})
    type{}                  <-->     type({})

Lua 还为面向对象调用提供了一种特殊语法,即冒号运算符。像 o:foo(x) 这样的表达式只是编写 o.foo(o, x) 的另一种方式,即调用 o.foo,并添加 o 作为第一个额外参数。在 第 16 章 中,我们将更详细地讨论此类调用(以及面向对象编程)。

Lua 程序使用的函数可以在 Lua 和 C(或主机应用程序使用的任何其他语言)中定义。例如,所有库函数都是用 C 编写的;但这一事实与 Lua 程序员无关。在调用函数时,用 Lua 定义的函数和用 C 定义的函数之间没有区别。

正如我们在其他示例中看到的那样,函数定义具有传统语法;例如

    -- add all elements of array `a'
    function add (a)
      local sum = 0
      for i,v in ipairs(a) do
        sum = sum + v
      end
      return sum
    end
在该语法中,函数定义有一个名称(在前面的示例中为 add)、一个参数列表和一个主体,它是一个语句列表。

参数的工作方式与局部变量完全相同,它使用函数调用中给出的实际参数进行初始化。您可以使用不同于其参数数量的参数数量来调用函数。Lua 会将参数数量调整为参数数量,就像在多重赋值中一样:多余的参数会被丢弃;多余的参数会获得 nil。例如,如果我们有一个像这样的函数

    function f(a, b) return a or b end
我们将有以下参数到参数的映射
    CALL             PARAMETERS
       
    f(3)             a=3, b=nil
    f(3, 4)          a=3, b=4
    f(3, 4, 5)       a=3, b=4   (5 is discarded)
尽管这种行为可能导致编程错误(在运行时很容易发现),但它也很有用,尤其适用于默认参数。例如,考虑以下函数,用于增加全局计数器。
    function incCount (n)
      n = n or 1
      count = count + n
    end
此函数的默认参数为 1;也就是说,调用 incCount()(无参数)将使 count 增加一。当您调用 incCount() 时,Lua 首先使用 nil 初始化 nor 导致其第二个操作数;结果 Lua 将默认 1 分配给 n