Lua 函数学习笔记

函数定义与调用

在 Lua 中,函数可以被定义并保存在变量中,也可以被直接定义并调用。以下是两种定义函数的方式:

luaCopy Code
-- 保存在变量中 local function add(a, b) return a + b end -- 直接定义和调用 print(function(a, b) return a + b end(2,3)) -- 输出 5

使用 function 关键字来定义函数,函数名可以省略,形参列表包含在一对小括号中,函数体则包含在 end 关键字之前。

函数调用时,使用函数名加上一对小括号并在其中传递实参即可。如果函数只有一个参数且该参数是字符串或表构造式,则可以省略小括号。

多重返回值和可变参数

Lua 函数允许返回多个值,这些值可以是任何类型。多个返回值可以通过元组的方式接收,也可以通过下标的方式获取某个具体返回值。

luaCopy Code
-- 返回多个值 function swap(a, b) return b, a end x, y = swap(1, 2) print(x, y) -- 输出 2 1 -- 可以忽略部分返回值 x = {swap(1, 2)} print(x[1]) -- 输出 2

此外,函数还支持可变参数。使用 ... 表示可变参数,在函数内部,它被视为一个包含所有传递的实参的数组。

luaCopy Code
-- 可变参数 function sum(...) local res = 0 for i, v in ipairs{...} do res = res + v end return res end print(sum(1, 2, 3, 4)) -- 输出 10

匿名函数和闭包

Lua 支持匿名函数,也叫 lambda 函数。与普通函数一样,匿名函数也可以被保存在变量中,也可以被作为实参传递给其他函数。

luaCopy Code
-- 匿名函数 local add = function(a, b) return a + b end print(add(1, 2)) -- 输出 3

匿名函数可以使用外部变量,这就引入了闭包的概念。闭包是指一个函数加上其所使用的外部变量所组成的整体。

luaCopy Code
-- 闭包 function outer() local a = 0 return function() a = a + 1 return a end end local f1 = outer() print(f1()) -- 输出 1 print(f1()) -- 输出 2 local f2 = outer() print(f2()) -- 输出 1

在以上示例中,函数 outer 返回了一个匿名函数,该匿名函数使用了 outer 中的局部变量 a,每次调用都会将 a 增加 1。由于 f1f2 都是 outer 返回的不同函数,它们各自维护着一个独立的 a,因此 f1f2 的调用互不干扰。

实例:计算表达式的值

以下是一个简单的示例,展示了如何使用 Lua 函数来计算表达式的值。

luaCopy Code
-- 计算表达式的值 function eval(expr) local stack = {} for token in string.gmatch(expr, "%S+") do if tonumber(token) then table.insert(stack, token) else local a = table.remove(stack) local b = table.remove(stack) if token == "+" then table.insert(stack, b + a) elseif token == "-" then table.insert(stack, b - a) elseif token == "*" then table.insert(stack, b * a) elseif token == "/" then table.insert(stack, b / a) end end end return stack[1] end print(eval("1 2 +")) -- 输出 3 print(eval("5 3 - 4 +")) -- 输出 6

以上示例中,eval 函数将传入的字符串表达式按空白符分割成多个单词,并根据运算符将数字和符号加入到一个栈中。最后通过栈顶元素得到计算结果。注意,在计算时先出栈的是被减数和被除数,而不是一般的左操作数。