📄 lua 5.1 参考手册.txt
字号:
return 和 break 只能被写在一个语句块的最后一句。如果你真的需要从语句块的中间 return 或是 break ,你可以使用显式的声名一个内部语句块。一般写作 do return end 或是 do break end,可以这样写是因为现在 return 或 break 都成了一个语句块的最后一句了。
2.4.5 - For 语句
for 有两种形式:一种是数字形式,另一种是一般形式。
数字形式的 for 循环,通过一个数学运算不断的运行内部的代码块。下面是它的语法:
stat ::= for Name `=′ exp `,′ exp [`,′ exp] do block end
block 将把 name 作循环变量。从第一个 exp 开始起,直到第二个 exp 的值为止,其步长为第三个 exp 。更确切的说,一个 for 循环看起来是这个样子
for v = e1, e2, e3 do block end
这等价于代码:
do
local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
if not (var and limit and step) then error() end
while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
local v = var
block
var = var + step
end
end
注意下面这几点:
所有三个控制表达式都只被运算一次,表达式的计算在循环开始之前。这些表达式的结果必须是数字。
var 、limit 、以及 step 都是一些不可见的变量。这里给它们起的名字都仅仅用于解释方便。
如果第三个表达式(步长)没有给出,会把步长设为 1 。
你可以用 break 来退出 for 循环。
循环变量 v 是一个循环内部的局部变量;当 for 循环结束后,你就不能在使用它。如果你需要这个值,在退出循环前把它赋给另一个变量。
一般形式的 for 通过一个叫作叠代器(iterators)的函数工作。每次叠代,叠代器函数都会被调用以产生一个新的值,当这个值为 nil 时,循环停止。一般形式的 for 循环的语法如下:
stat ::= for namelist in explist1 do block end
namelist ::= Name {`,′ Name}
for 语句好似这样
for var_1, ···, var_n in explist do block end
它等价于这样一段代码:
do
local f, s, var = explist
while true do
local var_1, ···, var_n = f(s, var)
var = var_1
if var == nil then break end
block
end
end
注意以下几点:
explist 只会被计算一次。它返回三个值, 一个叠代器函数,一个状态,一个叠代器的初始值。
f、 s、 以及 var 都是不可见的变量。这里给它们起的名字都只是为了解说方便。
你可以使用 break 来跳出 for 循环。
循环变量 var_i 对于循环来说是一个局部变量;你不可以在 for 循环结束后继续使用。如果你需要保留这些值,那么就在循环结束前赋值到别的变量里去。
2.4.6 - 把函数调用作为语句段
为了允许使用可能的副作用,函数调用可以被作为一个语句段执行:
stat ::= functioncall
在这种情况下,所有的返回值都被舍弃。函数调用在 §2.5.8 中解释。
2.4.7 - 局部变量声名
局部变量可以在语句块中任何地方声名。声名可以包含一个初始化赋值操作:
stat ::= local namelist [`=′ explist1]
如果有的话,初始化赋值操作的行为等同于赋值操作(参见 §2.4.3)。否则,所有的变量将被初始化为 nil。
一个 chunk 同时也是一个语句块(参见 §2.4.1),所以局部变量可以放在 chunk 中那些显式注明的语句块之外。这些局部变量的作用范围从声明起一直延伸到 chunk 末尾。
局部变量的可见规则在 §2.6 中解释。
2.5 - 表达式
Lua 中有这些基本表达式:
exp ::= prefixexp
exp ::= nil | false | true
exp ::= Number
exp ::= String
exp ::= function
exp ::= tableconstructor
exp ::= `...′
exp ::= exp binop exp
exp ::= unop exp
prefixexp ::= var | functioncall | `(′ exp `)′
数字和字符串在 §2.1 中解释;变量在 §2.3 中解释;函数定义在 §2.5.9 中解释;函数调用在 §2.5.8 中解释; table 的构造在 §2.5.7 中解释;可变参数的表达式写作三个点 ('...') ,它只能被用在有可变参数的函数中;这些在 §2.5.9 中解释。
二元操作符包含有数学运算操作符(参见 §2.5.1),比较操作符(参见 §2.5.2),逻辑操作符(参见 §2.5.3),以及连接操作符(参见 §2.5.4)。一元操作符包括负号(参见see §2.5.1),取反 not(参见 §2.5.3),和取长度操作符(参见 §2.5.5)。
函数调用和可变参数表达式都可以放在多重返回值中。如果表达式作为一个独立语句段出现(参见 §2.4.6)(这只能是一个函数调用),它们的返回列表将被对齐到零个元素,也就是忽略所有返回值。如果表达式用于表达式列表的最后(或者是唯一)的元素,就不会有任何的对齐操作(除非函数调用用括号括起来)。在任何其它的情况下,Lua 将把表达式结果看成单一元素,忽略除第一个之外的任何值。
这里有一些例子:
f() -- 调整到 0 个结果
g(f(), x) -- f() 被调整到一个结果
g(x, f()) -- g 被传入 x 加上所有 f() 的返回值
a,b,c = f(), x -- f() 被调整到一个结果 ( c 在这里被赋为 nil )
a,b = ... -- a 被赋值为可变参数中的第一个,
-- b 被赋值为第二个 (如果可变参数中并没有对应的值,
-- 这里 a 和 b 都有可能被赋为 nil)
a,b,c = x, f() -- f() 被调整为两个结果
a,b,c = f() -- f() 被调整为三个结果
return f() -- 返回 f() 返回的所有结果
return ... -- 返回所有从可变参数中接收来的值
return x,y,f() -- 返回 x, y, 以及所有 f() 的返回值
{f()} -- 用 f() 的所有返回值创建一个列表
{...} -- 用可变参数中的所有值创建一个列表
{f(), nil} -- f() 被调整为一个结果
被括号括起来的表达式永远被当作一个值。所以, (f(x,y,z)) 即使 f 返回多个值,这个表达式永远是一个单一值。((f(x,y,z)) 的值是 f 返回的第一个值。如果 f 不返回值的话,那么它的值就是 nil 。)
2.5.1 - 数学运算操作符
Lua 支持常见的数学运算操作符:二元操作 + (加法), - (减法),* (乘法), / (除法), % (取模),以及 ^ (幂);和一元操作 - (取负)。如果对数字操作,或是可以转换为数字的字符串(参见 §2.2.1),所有这些操作都依赖它通常的含义。幂操作可以对任何幂值都正常工作。比如, x^(-0.5) 将计算出 x 的平方根。取模操作被定义为
a % b == a - math.floor(a/b)*b
这就是说,其结果是商相对负无穷圆整后的余数。(译注:负数对正数取模的结果为正数)
2.5.2 - 比较操作符
Lua 中的比较操作符有
== ~= < > <= >=
这些操作的结果不是 false 就是 true。
等于操作 (==) 首先比较操作数的类型。如果类型不同,结果就是 false。否则,继续比较值。数字和字符串都用常规的方式比较。对象 (table ,userdata ,thread ,以及函数)以引用的形式比较:两个对象只有在它们指向同一个东西时才认为相等。每次你创建一个新对象(一个 table 或是 userdata ,thread 函数),它们都各不相同,即不同于上次创建的东西。
你可以改变 Lua 比较 table 和 userdata 的方式,这需要使用 "eq" 这个原方法(参见 §2.8)。
§2.2.1 中提及的转换规则并不作用于比较操作。所以, "0"==0 等于 false,而且 t[0] 和 t["0"] 描述的是 table 中不同的域。
操作符 ~= 完全等价于 (==) 操作的反值。
大小比较操作以以下方式进行。如果参数都是数字,那么就直接做数字比较。否则,如果参数都是字符串,就用字符串比较的方式进行。再则,Lua 就试着调用 "lt" 或是 "le" 元方法(参见 §2.8)。
2.5.3 - 逻辑操作符
Lua 中的逻辑操作符有 and, or, 以及 not。和控制结构(参见 §2.4.4)一样,所有的逻辑操作符把 false 和 nil 都作为假,而其它的一切都当作真。
取反操作 not 总是返回 false 或 true 中的一个。与操作符 and 在第一个参数为 false 或 nil 时返回这第一个参数;否则,and 返回第二个参数。或操作符 or 在第一个参数不为 nil 也不为 false 时,返回这第一个参数,否则返回第二个参数。 and 和 or 都遵循短路规则;也就是说,第二个操作数只在需要的时候去求值。这里有一些例子:
10 or 20 --> 10
10 or error() --> 10
nil or "a" --> "a"
nil and 10 --> nil
false and error() --> false
false and nil --> false
false or nil --> nil
10 and 20 --> 20
(在这本手册中, --> 指前面表达式的结果。)
2.5.4 - 连接符
Lua 中字符串的连接操作符写作两个点 ('..')。如果两个操作数都是字符串或都是数字,连接操作将以 §2.2.1 中提到的规则把其转换为字符串。否则,会取调用元方法 "concat" (参见 §2.8)。
2.5.5 - 取长度操作符
取长度操作符写作一元操作 #。字符串的长度是它的字节数(就是以一个字符一个字节计算的字符串长度)。
table t 的长度被定义成一个整数下标 n 。它满足 t[n] 不是 nil 而 t[n+1] 为 nil;此外,如果 t[1] 为 nil ,n 就可能是零。对于常规的数组,里面从 1 到 n 放着一些非空的值的时候,它的长度就精确的为 n,即最后一个值的下标。如果数组有一个“空洞” (就是说,nil 值被夹在非空值之间),那么 #t 可能是任何一个是 nil 值的位置的下标(就是说,任何一个 nil 值都有可能被当成数组的结束)。
2.5.6 - 优先级
Lua 中操作符的优先级写在下表中,从低到高优先级排序:
or
and
< > <= >= ~= ==
..
+ -
* / %
not # - (unary)
^
通常,你可以用括号来改变运算次序。连接操作符 ('..') 和幂操作 ('^') 是从右至左的。其它所有的操作都是从左至右。
2.5.7 - Table 构造
table 构造子是一个构造 table 的表达式。每次构造子被执行,都会构造出一个新的 table 。构造子可以被用来构造一个空的 table,也可以用来构造一个 table 并初始化其中的一些域。一般的构造子的语法如下
tableconstructor ::= `{′ [fieldlist] `}′
fieldlist ::= field {fieldsep field} [fieldsep]
field ::= `[′ exp `]′ `=′ exp | Name `=′ exp | exp
fieldsep ::= `,′ | `;′
每个形如 [exp1] = exp2 的域向 table 中增加新的一项,其键值为 exp1 而值为 exp2。形如 name = exp 的域等价于 ["name"] = exp。最后,形如 exp 的域等价于 [i] = exp , 这里的 i 是一个从 1 开始不断增长的数字。这这个格式中的其它域不会破坏其记数。举个例子:
a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }
等价于
do
local t = {}
t[f(1)] = g
t[1] = "x" -- 1st exp
t[2] = "y" -- 2nd exp
t.x = 1 -- t["x"] = 1
t[3] = f(x) -- 3rd exp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -