variable number of arguments :变长参数,指函数可以拥有不同数量的实参。
当函数需要一个或者多个参数时,可以使用...代替这些参数。此时...为表达式,表达式...的行为类似于一个具有多重返回值的函数,返回当前函数的所有参数。
e.g.
function add(...)
local s = 0
for i,v in ipairs{...} do --{...} 代表一个由变长参数组成的数组
s = s+v
end
return s
end
print(add(3,4,5,6,7)) -->25
既然...是表达式,就可以赋值给变量a,b:local a, b = ...
同样,变长参数也能拥有任意数量的固定参数,只需要将固定参数放在变长参数之前即可,那么余下的参数就属于变长参数。
e.g.
function fwirte(fmt,...) --fmt为固定参数
return io.write(string.format(fmt,...))
end
fwrite() --fmt = nil,无变长参数
fwrite("a") --fmt="a" ,无变长参数
fwrite("%d%d",4,5) --fmt="%d%d" ,变长参数4,5
通常使用{...}即可访问变长参数,但是当变长参数中间包含一些nil值时就会出现问题
function test(...)
for i,v in ipairs{...} do
print(v)
end
end
test(1,2,3) --> 1 2 3
test(1,2,3,nil) --> 1 2 3
test(1,2,3,nil ,4) --> 1 2 3
遍历时当遇到数组中的nil即终止遍历
此时需要使用函数select来访问变长参数。调用select,必须传入一个固定参数selector和一系列变长参数。如果selector = n,则返回弟n个可变实参,否则selector只能为#,select函数返回变长参数的总长度(包含nil,即使nil为最后一个值)。
print(select("#",1,2,3,nil)) -->4
for i=1,select("#",...) do --select("#",...)返回变长参数总数
local arg = select(i,...) --获的第i个参数
<循环体>
end
具名实参(named arguments):顾名思义,指具有名称的实参。
很多时候,当我们进行函数调用时,如果函数具有多个参数,我们往往会记不清各个参数代表什么意思。而lua的参数传递机制是具有位置性的,即实参是通过参数表中的位置和形参匹配起来的。这时该怎么办呢,如果能给实参指定具体的名字,不是就可以解决记不清参数代表什么了的问题了吗?
于是我们想这样调用函数:rename(old = "temp.lua", new = "temp1.lua") 但是lua不支持这种语法。
但是如果将这些具有名字的实参,组织到一个table构造式里,就ok了。
rename{old= "temp.lua", new = "temp1.lua"} -- 当实参只有一个table构造式时,函数圆括号可有可无
然后,我们在修改rename函数定义,将其改为只接受一个参数,并从这个参数中获取实际的参数
function rename(arg)
return os.rename(arg.old, arg.new)
end
e.g.2
在一个GUI库中,一个创建新窗口的函数可能具有许多参数,其中大部分是可选的,这是使用具名参数就很好
比如window函数里面会检查一些必填参数,或为某些参数添加默认值,然后调用_Window真正用于创建新窗口,而且要求所有的参数按照正确的次序传入。
那么可以这样写:
function window(opotions)
-- 检查必填参数
if type(options.title) ~= "string" then
error("no title")
elseif type(options.width) ~= "number" then
error("no width")
elseif type(options.height) ~= "number" then
error("no height")
end
--其他的参数都是可选的
_Window(options.title,
options.x or 0, -- 默认值为0
options.y or 0, -- 默认值为0
options.width, options.height,
options.background or "white", -- 默认值为 white
options.border -- 默认值nil
)
end