函数调用教程

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

注意:在 Lua 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() 是一个很有用的函数,用于处理可变参数。它接受一个表并返回一个变量列表,例如:

> = 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

RecentChanges · preferences
编辑 · 历史
最后编辑于 2013 年 4 月 4 日 下午 7:40 GMT (差异)