函数调用教程

lua-users home
wiki

本教程紧接函数教程

传递参数

由于 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
同样,没有错误,最后一个参数被忽略。由于 Lua 是动态类型的,我们可以传递任何类型的参数。例如,我们可以传递字符串以及数字或引用。
> 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

最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2013 年 4 月 5 日凌晨 1:40 GMT (差异)