争取两三周入门Lua!
本文简要介绍了Lua的“局部变量和代码块”,"控制结构等"基础语法部分。
局部变量和代码块
Lua语言中的变量在默认情况下是 全局变量,所有的局部变量在使用前必须用local声明。局部变量的生效范围仅限于声明它的代码块。在交互模式中,每一行代码就是一个代码段(除非这行代码不完整)。
可以用do-end显式区分一个代码块:
do
local a2 = 2 * a
end
运行时动态替换
也称猴子补丁(Monkey patching):
local foo = foo
这段代码声明了一个局部变量foo,使用全局变量foo对其初始化。这个用法在需要提高对foo的访问速度时很有用;当其他函数改变了全局foo的值,而代码段又需要全局foo的原始值时,这个用法也很有用。
除了可以替换变量外,也能替换函数,例如local print = print,在此之前用的都是默认print,在此之后用的是自定义print。
尽可能地使用局部变量是一种良好的编程风格:
- 局部变量可以避免由于不必要的命名而造成全局变量的混乱;
- 局部变量还能避免同一程序中不同代码部分中的命名冲突;
- 访问局部变量比访问全局变量更快;
- 局部变量会随着其作用域的结束而消失,使得GC能够将其释放。
控制结构
Lua提供了一组精简常用的控制结构:
- 用于条件执行的
if; - 用于循环的
while,repeat,for;
所有控制结构语法上都有一个显式的终结符:
end用于终结if,for和while结构;until用于终结repeat结构。
if then else
if op == "+" then
r = a + b
elseif op == "-" then
r = a - b
end
Lua语言不支持switch语句。
while
先测试条件是否为真,是的话就循环,否则循环结束。
local i = 1
while a[i] do
print(a[i])
i = i + 1
end
repeat
重复执行循环体直到条件为真时结束,由于条件测试在循环体之后执行,所以循环体至少会执行一次。
-- 牛顿迭代法求平方根
local sqr = x / 2
repeat
sqr = (sqr + x / sqr) / 2
local error = math.abs(sqr^2 - x)
until error < x / 10000
可以发现,循环体内声明的局部变量作用域包括测试条件。
for
数值型
for var = st, ed [, step] do
sth
end
在循环中,var的值从st以步长(可选,默认为1)step增长至ed,每步执行一次sth。如果不想设置上限,可以让ed = math.huge。
要注意的是,循环变量var的作用域仅限于循环体内。
泛型
泛型for遍历迭代函数返回的所有值,例如pairs,ipairs,io.lines()等,利用好可以遍历几乎所有数据结构。
function add(...)
local sum = 0
for _, v in ipairs{...} do
sum = sum + v
end
return sum
end
泛型for可以使用多个变量,每次循环时会更新这些变量。当第一个变量为nil时,循环终止。
break, return和goto
break和return语句用于从当前的循环结构中跳出;goto语句则允许跳转到函数中的几乎任何地方。
这里看一下goto,它用于将当前程序跳转到相应的标签处继续执行。在使用goto跳转时,Lua语言设置了一些限制条件:
- 标签遵循常见的可见性规则,因此不能直接跳转到一个代码块中的标签(该标签对外不可见)
goto不能跳转到函数外goto不能跳转到局部变量的作用域
goto语句在编写状态机时也很有用,如下代码用于检验输入是否包含偶数个0:
-- 标签语法: ::标签名::
::s1:: do
local c = io.read(1)
if c == '0' then goto s2
elseif c == nil then print 'ok'; return
else goto s1
end
end
::s2:: do
local c = io.read(1)
if c == '0' then goto s1
else if c == nil then print 'not ok'; return
else goto s2
end
end
goto s1