Chapter 4: Statements
Lua 除支持类似C 的常规语句外,还支持多赋值,局部变量声明等。
4.1 Assignment
赋值
a = "hello" .. "world"
t.n = t.n + 1
多赋值
a, b = 10, 2*x -- a gets 10, b gets 2*x
利用多赋值交换两个变量
x, y = y, x -- swap 'x' for 'y'
a[i], a[j] = a[j], a[i] -- swap 'a[i]' for 'a[j]'
多赋值右侧过少用nil 补,过多直接丢弃
a, b, c = 0, 1
print(a, b, c) --> 0 1 nil
a, b = a+1, b+1, b+2 -- value of b+2 is ignored
print(a, b) --> 1 2
a, b, c = 0
print(a, b, c) --> 0 nil nil
多赋值不比同等的单赋值快。
多赋值最常使用的场合是让一个函数返回多个值 a,b=f()。
参见5.1 小节
多赋值也常用于交换两个变量。
4.2 Local Variables and Blocks
带 local 的变量是局部变量
j = 10 -- global variable
local i = 1 -- local variable
局部变量的有效范围限于它们声明的地方 —— 控制结构内部、函数体、一个文件,或string
x = 10
local i = 1 -- local to the chunk
while i <= x do
local x = i*2 -- local to the while body
print(x) --> 2, 4, 6, 8, ...
i = i + 1
end
if i > 20 then
local x -- local to the "then" body
x = 20
print(x + 2) -- (would print 22 if test succeeded)
else
print(x) --> 10 (the global one)
end
print(x) --> 10 (the global one)
注意这个例子在交互环境中不能像预期的那样正常工作。在交互模式中,所有的行都是一个chunk(除非它不是一个完整命令)。这样,local 声明的局部变量在下一行就无效了。关键字do.end. 可以避免这一状况,只要让local 在do.end 内部声明既可。
do.end 把里面的所有东西都变成一个chunk(类似C 里面用{}把好多东西括起来)
do
local a2 = 2*a
local d = (b^2 - 4*a*c)^(1/2)
x1 = (-b + d)/a2
x2 = (-b - d)/a2
end -- scope of 'a2' and 'd' ends here
print(x1, x2)
尽可能多的使用局部变量是一种良好编程风格。此外,访问局部变量要比全局变量快。
局部变量在超过有效范围后会自动被垃圾回收器处理掉。
未赋初值的局部变量自动初始化为nil
local a, b = 1, 10
if a < b then
print(a) --> 1
local a -- '= nil' is implicit
print(a) --> nil
end -- ends the block started at 'then'
print(a, b) --> 1 10
Lua 习惯用法
local foo = foo
创建一个局部变量foo,并初始化为全局变理foo
当需要保留原始值时,这种惯用法很有效。而且还提高了对foo 的访问速度。
4.3 Control Structures
if then else end
if a < 0 then a = 0 end
if a < b then return a else return b end
if line > MAXLINES then
showpage()
line = 0
end
elseif then
if op == "+" then
r = a + b
elseif op == "-" then
r = a - b
elseif op == "*" then
r = a*b
elseif op == "/" then
r = a/b
else
error("invalid operation")
end
Lua 没有switch 语句,就用if 语句代替。
while do end
local i = 1
while a[i] do
print(a[i])
i = i + 1
end
repeat until
-- print the first non-empty input line
repeat
line = os.read()
until line ~= ""
print(line)
当两个值的差小于某个值时既出循环。
local sqr = x/2
repeat
sqr = (sqr + x/sqr)/2
local error = math.abs(sqr^2 - x)
until error < x/10000 -- 'error' still visible here
注意局部变量到until 这一句扔然有效。
Numeric for
for var=exp1,exp2,exp3 do
<something>
end
其语义是 exp1 to exp2 , step by exp3
exp3 可选,默认值是1
for i=1,f(x) do print(i) end
for i=10,1,-1 do print(i) end
如希望没有上界限制,exp2用math.huge
for i=1,math.huge do
if (0.3*i^3 - 20*i^2 - 500 >= 0) then
print(i)
break
end
end
for 里的变量出了循环就无效了
for i=1,10 do print(i) end
max = i -- probably wrong! 'i' here is global
如需保留for 里的变量,将其存进另一变量
-- find a value in a list
local found = nil
for i=1,#a do
if a[i] < 0 then
found = i -- save value of 'i'
break
end
end
print(found)
exp1,exp2,exp3 都只计算一次,for i=1,f(x) do print(i) end 中的f(x) 只计算一次。
不要改变for 中控制变量的值。如需正常退出循环前中止,用break
Generic for (功能类似foreach)
Lua 基础库提供ipairs 函数,获得表的index 和value
-- print all values of array 'a'
for i,v in ipairs(a) do print(v) end
Lua 基础库提供pairs 函数,获得表的index
-- print all keys of table 't'
for k in pairs(t) do print(k) end
一个更具体的例子
days = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"}
revDays = {["Sunday"] = 1, ["Monday"] = 2,
["Tuesday"] = 3, ["Wednesday"] = 4,
["Thursday"] = 5, ["Friday"] = 6,
["Saturday"] = 7}
x = "Tuesday"
print(revDays[x]) --> 3
revDays = {}
for k,v in pairs(days) do
revDays[v] = k
end
4.4 break and return
break
local i = 1
while a[i] do
if a[i] == v then break end
i = i + 1
end
return
return 的一个特殊之处
function foo ()
return --<< SYNTAX ERROR
-- 'return' is the last statement in the next block
do return end -- OK
<other statements>
end