基础
Lua 的函数参数,只有位置参数(positional),没有命名参数。
函数调用的简化写法
当参数只有一个、且为 string literal 或 table constructor 时,调用一个函数时参数列表可以不用 ()
包裹:
print "hello world" -- 等同于 print("hello world")
type{} -- 等同于 type({})
但我觉得这种节约没有意义。
参数匹配
调用函数时,Lua 不要求传参数量一致:
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
函数多返回值
Lua 支持多返回值;支持在一个语句(statement)中实现多次赋值(multiple assignments)。但多返回值的机制有点 tricky:仅当多返回值的函数,作为多赋值语句中的唯一或最后一方时,它的多个值都会被返回;不然仅使用其第一个值。代码表示下:
function foo0 () end
function foo1 () return "a" end
function foo2 () return "a", "b" end
x, y = foo2() --> x="a", y="b"
x = foo2() --> x="a", "b" is discarded
x, y, z = 10, foo2() --> x=10, y="a", z="b"
x, y = foo0() --> x=nil, y=nil
x, y = foo1() --> x="a", y=nil
x, y, z = foo2() --> x="a", y="b", z=nil
-- 函数不在最后一位时,仅有第一个返回值起作用
x, y = foo2(), 20 --> x="a", y=20 ("b" is discarded)
x, y = foo0(), 20, 30 --> x=nil, y=20 (30 is discarded)
print(foo2()) --> a b
print((foo2())) --> a
print(foo2(), 1) --> a 1
print(foo2() .. "x") --> ax
t = {foo2()} --> t = {"a", "b"}
t = {foo0(), foo2(), 4} --> t[1] = nil, t[2] = "a", t[3] = 4
本质上是 Lua 的多返回值机制设计得不够严谨。如果像 Python 一样有 tuple 来承载多返回值,就不需要搞得这么复杂。
可变参数函数
就是把 ...
当成多个值:
function add (...)
local s = 0 for _, v in ipairs{...} do
s = s + v
end
return s
end
print(add(3, 4, 10, 25, 12)) --> 54
function p(...)
local a, b = ...
print(a, b)
end
p(1) --> 1 nil
p(3, 4) --> 3 4
function p2(...)
print(...)
print(..., 10)
print(20, ...)
end
-- 跟函数多返回值一样,不在最后面时就仅有第一个值起效
> p2(3, 4)
3 4
3 10
20 3 4
-- `unpack` 函数(Lua 5.1)及后面的 `table.unpack` 函数(Lua 5.2 起),
-- 可以把一个 table unpack 成多个参数
t = {"hello", "world"}
print(table.unpack(t))