函数调用教程 |
|
由于 Lua 是动态类型的,并且不需要函数类型声明,因此检查函数所需的参数数量和类型似乎有些多余。Lua 可以优雅地处理调用参数和形式参数数量不匹配的情况。如果形式参数没有被填充,则会收到默认值为nil
。如果传递了太多参数,它们会被简单地忽略。每个参数都没有指定类型,因为它们是动态类型的。也就是说,我们只需要在使用对象时知道它的类型,而不需要在引用它时知道。我们将使用以下函数作为示例
> function foo(a,b,c) print(a,b,c) end
> foo() nil nil nil
nil
,或无值,并且我们没有收到错误。以下是我们传递太多参数时发生的情况
> foo(1,2,3,4) 1 2 3
> foo("hello") hello nil nil > foo("pi", 3.1415, { comment="this is a table" }) pi 3.1415 table: 0x21d49b0
函数通常需要可变数量的参数。例如,C 中的printf(format,...)
函数。Lua 实现此功能的一种方法是将可变参数列表放入名为arg
的数组表中,函数可以使用该表。例如,
> function foo(...) print(arg) end > foo("abc",3,77) table: 0x21d56a0
注意:在 5.2 中,arg
已被弃用,可以使用三个点 (...
) 来代替,效果类似。
> function foo(...) print(...) end (In some cases, the argument list array must be referenced by placing the three periods within a set of curly braces.) > function foo(...) for k,v in pairs({...}) do print(k,v) end end
在这个例子中,我们只能看到这是一个表。我们可以使用table.foreach(table,function)
来打印可变参数表的数值,但使用pairs()
更好,因为table.foreach()
在 Lua 5.1 中已被弃用。
> function foo(...) for k,v in pairs(arg) do print(k,v) end end > foo() n 0
从查看一个空的可变参数列表可以很容易地看出,添加了一个额外的表对来提供表中元素的数量,arg.n
。在这种情况下,参数数量为零。让我们尝试传递可变数量的参数
> foo(1,2,3) 1 1 2 2 3 3 n 3 > foo("apple",2,"banana",99,3.1415927,foo) 1 apple 2 2 3 banana 4 99 5 3.1415927 6 function: 0x9ecd20 n 6
另一种方法是使用...
作为占位符
> function foo(...) print('x', select(2, ...), 'y', ...) end > foo("apple", "banana", "orange") x banana y apple banana orange
...
还有一个额外的好处,它避免了在构建arg
表时的小性能损失。
unpack()
是用于可变参数的一个有用函数。它接受一个表并返回一个变量列表,例如:
> = unpack({1,2,3})
1 2 3
这可以与可变参数列表一起使用,如下所示
> function listargs(...) >> return unpack(arg) >> end > = listargs({1,2,3}) 1 2 3 > = listargs({"hello", {1,2,3}, function (x) return x*x end}) hello table: 0x9efed0 function: 0x9eec40
它也可以用来将可变数量的参数传递给函数,如下所示
> function countargs(...) >> return #arg >> end > = countargs(1,2,3) 3 > = countargs(unpack{1,2,3}) 3
要了解unpack的工作原理,请查看这个缓慢的伪实现
> function unpack (t, i) >> i = i or 1 >> if t[i] ~= nil then >>> return t[i], unpack(t, i + 1) >> end > end
摘自 Lua 参考手册:[第 5.1 章 - 多个结果].
Lua 可以从函数返回多个值。这是通过返回用逗号分隔的值列表来完成的
> function foo(angle) >> return math.cos(angle), math.sin(angle) >> end > > print( foo(1) ) -- returns 2 values... 0.54030230586814 0.8414709848079 > > c,s = foo(3.142/3) -- assign the values to variables > = math.atan(s/c) 1.0473333333333 > = c,s 0.49988240461137 0.86609328686923 > > function many(x) >> return x, x*x, x*x*x, x*x*x*x, x*x*x*x*x >> end > = many(5) 5 25 125 625 3125 > = many(0.9) 0.9 0.81 0.729 0.6561 0.59049
如果我们构建一个包含值的表并使用unpack
,上面的函数可以具有可变数量的返回值。例如:
> function many2(x,times) >> local t = {} >> for i=1,times do t[i] = x^i end >> return unpack(t) >> end > = many2(5,10) 5 25 125 625 3125 15625 78125 390625 1953125 9765625 > = many2(0.5,7) 0.5 0.25 0.125 0.0625 0.03125 0.015625 0.0078125
我们也可以在表中返回这些值。为此,我们在函数调用周围添加花括号,这将构建一个表,即
以下是一个使用前面函数示例的示例
> = { foo(1.5) } table: 0x204e100 > t = { foo(1.5) } > for k,v in ipairs(t) do print(k,v) end 1 0.070737201667703 2 0.99749498660405
如果函数返回多个值,但我们只想要第一个值,我们在函数调用周围加上括号,即
> = (foo(1.5)) 0.070737201667703 > = foo(1.5) 0.070737201667703 0.99749498660405
可以通过返回一个表并取第一个元素来实现相同的效果,但上面的语法效率更高。例如:
> = ({foo(1.5)}) [1] 0.070737201667703