在 Lua
语言中,函数( Function
)是对语句和表达式进行抽象的主要方式。函数既可以用于完成某种特定任务(有时在其他语言中也被称为过程(procedure)或子历程(subroutine)),也可以只是进行一些计算然后返回计算结果。在前一种情况下,我们将一句函数调用视为一条语句;而在后一种情况下,我们则将函数调用视为表达式:
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
语言也为面向对象风格的调用(object-oriented call)提供了一种特殊的语法,即冒号操作符。形如 o:foo(x)
的表达式意为调用对象 o
的 foo
方法。
一个 Lua
程序既可以调用 Lua
语言编写的函数,也可以调用C语言(或者宿主程序使用的其他任意语言)编写的函数。一般来说,我们选择使用C语言编写的函数来实现对性能要求更高,或不容易直接通过 Lua
语言进行操作的操作系统机制等。例如, Lua
语言标准库中所有的函数都是使用C语言编写的。不过,无论一个函数是用 Lua
语言编写的还是用C语言编写的,在调用他们时都没有任何区别。
Lua
语言中的函数定义的常见语法格式如下:
-- 对序列'a'中的元素求和 function add (a) local sum = 0 for i = 1, #a do sum = sum + a[i] end return sum end
在这种语法中,一个函数定义具有一个函数名、一个参数组成的列表和由一组语句组成的函数体。参数的行为与局部变量的行为完全一致,相当于一个用函数调用时传入的值进行初始化的局部变量。
调用函数时使用的参数个数可以与定义函数时使用的参数个数不一致。 Lua
语言会通过抛弃多余参数和将不足的参数设为 nil
的方式来调整参数的个数。
function f (a, b) print(a, b) end
其行为如下:
f() --> nil nil f(3) --> 3 nil f(3, 4) --> 3 4 f(3, 4, 5) --> 3 4 (5被丢弃)
虽然这种行为可能导致编程错误(在单元测试中容易发现),但同样又是有用的,尤其是对于默认参数的情况。例如对下面的递增全局计数器函数:
function incCount (n) n = n or 1 globalCounter = globalCounter + n end
该函数以 1
作为默认实参,当调用无参数的 incCount()
时,将 globalCounter
加 1
。在调用 incCount()
时, Lua
语言首先把参数 n
初始化为 nil
,接下来的 or
表达式又返回了其第二个操作数,最终把 n
赋成了默认值 1
。