Lua函数概括

函数

function f(a, b) print(a, b) end

多返回值

function foo0() end -- 不返回结果
function foo1() return "a" end -- 返回1个结果
function foo2() return "a", "b" end -- 返回2个结果
  • 函数调用将产生尽可能多的返回值以匹配待赋值变量
x, y = foo2() -- x="a", y="b"
x = foo2() -- x="a", "b"被丢弃
x, y, z = 10, foo2() -- x="10", y="a", z="b"
  • 返回值或返回值个数不够多,Lua会用nil来补充
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'被丢弃)
x, y = foo0(), 20 , 30 -- x = nil, y = 20 (30被丢弃)
  • 函数返回参数 和 函数自动匹配
function foo3(a, b) print(a, b) end
foo3(foo2()) --> a b
  • 表构造器会完整接受函数调用的返回值,只有当函数调用是表达式列表中最后一个时才有效,其他位置只返回1个结果
t = {foo0()} -- t = {}
t = {foo1()} -- t = {"a"}
t = {foo2()} -- t = {"a", "b"}
  • 返回值加括号只返回一个值
print((foo0())) --> nil
print((foo1())) --> a
print((foo2())) --> a
  • return (f(x)) 也是返回第一个值

可变长参数函数

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 foo (a, b, c) end
-- 等价于
function foo (...) local a, b, c = ... end
function fwrite (fmt, ...)
	return io.write(string.format(fmt, ...))
end
  • table.pack 将可变参数组成数组
function nonils(...)
	local args = table.pack(...)
	for i = 1, args.n do
		if args[i] == nil then return return false end
	end
	return true
end

print(nonils(2, 3, nil)) --> false
print(nonils(2, 3)) --> true
print(nonils()) --> true
print(nonils(nil)) --> false
  • 函数select
  1. 如果select是数值n,那么返回第n个参数的所有参数
  2. 字符串“#”, 返回额外参数的总数
print(select(1, "a", "b", "c")) --> a b c
print(select(2, "a", "b", "c")) --> b c
print(select(3, "a", "b", "c")) --> c
print(select("#", "a", "b", "c")) --> 3
function add(...)
	local s = 0
	for i = 1, select("#", ...) do
		s = s + select(i, ...)
	end
	return s
end

函数table.unpack

  • 真实列表转换成一组返回值
print(table.unpack{10, 20, 30})  --> 10 20 30
a, b = table.unpack(10, 20 ,30) --> a = 10, b = 20, 30被丢弃
  • unpack的泛型使用(重要)
print(string.find("hello", "l"))
-- 等价于泛型方法
f = string.find
a = {"hello", "ll"}
print(f(table.unpack(a)))
  • 限制返回元素的范围
print(table.unpack({"Sun", "Mon", "Tue", "Wed"}, 2, 3)) --> Mon Tue
  • unpack 函数是用C函数实现,这里用lua实现
function unpack(t, i, n)
	i = i or 1
	n = n or #t
	if i <= n then
		return t[i], unpack(t, i+1, n)
	end
end

正确的尾调用(tail call)

function f(x) x = + 1; return g(x) end

在lua中,由于f函数在执行完g函数后,f也就结束了,所以在执行g函数中,不需要保留f函数栈,所以在执行g函数时,f的栈就已经被销毁了

所以,该函数永远不会发生栈溢出

function foo(n)
	if n > 0 then return foo(n - 1) end
end
  • 只有 return func(args) 的调用才是tail call

以下都不是

function f(x) g(x) end
function f(x) return g(x) + 1 end
function f(x) return x or g(x) end
function f(x) return (g(x)) end