📄 lua 5_1 参考手册.htm
字号:
</PRE>
<P>一个语句块可以被显式的写成一个单独的语句段: <PRE> stat ::= <B>do</B> block <B>end</B>
</PRE>
<P>显式的语句块对于控制变量的作用范围很有用。有时候,显式的语句块被用来在另一个语句块中插入 <B>return</B> 或是 <B>break</B>
(参见 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.4.4">§2.4.4</A>)。
<H3>2.4.3 - <A name=2.4.3>赋值</A></H3>
<P>Lua 允许多重赋值。因此,赋值的语法定义是等号左边放一系列变量,而等号右边放一系列的表达式。两边的元素都用逗号间开: <PRE> stat ::= varlist1 `<B>=</B>´ explist1
varlist1 ::= var {`<B>,</B>´ var}
explist1 ::= exp {`<B>,</B>´ exp}
</PRE>
<P>表达式放在 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5">§2.5</A> 里讨论。
<P>在作赋值操作之前,那一系列的右值会被对齐到左边变量需要的个数。如果右值比需要的更多的话,多余的值就被扔掉。如果右值的数量不够需求,将会按所需扩展若干个
<B>nil</B>。如果表达式列表以一个函数调用结束,这个函数所返回的所有值都会在对齐操作之前被置入右值序列中。(除非这个函数调用被用括号括了起来;参见 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5">§2.5</A>)。
<P>赋值段首先会做运算完所有的表达式,然后仅仅做赋值操作。因此,下面这段代码 <PRE> i = 3
i, a[i] = i+1, 20
</PRE>
<P>会把 <CODE>a[3]</CODE> 设置为 20,而不会影响到 <CODE>a[4]</CODE> 。这是因为 <CODE>a[i]</CODE>
中的 <CODE>i</CODE> 在被赋值为 4 之前就被拿出来了(那时是 3 )。简单说 ,这样一行 <PRE> x, y = y, x
</PRE>
<P>可以用来交换 <CODE>x</CODE> 和 <CODE>y</CODE> 中的值。
<P>对全局变量以及 table 中的域的赋值操作的含义可以通过 metatable 来改变。对变量下标指向的赋值,即 <CODE>t[i] =
val</CODE> 等价于 <CODE>settable_event(t,i,val)</CODE>。(关于函数
<CODE>settable_event</CODE> 的详细说明,参见 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.8">§2.8</A>。这个函数并没有在
Lua 中定义出来,也不可以被调用。这里我们列出来,仅仅出于方便解释的目的)
<P>对于全局变量的赋值 <CODE>x = val</CODE> 等价于 <CODE>_env.x = val</CODE>,这个又可以等价于 <PRE> settable_event(_env, "x", val)
</PRE>
<P>这里,<CODE>_env</CODE> 指的是正在运行中的函数的环境。(变量 <CODE>_env</CODE> 并没有在 Lua
中定义出来。我们仅仅出于解释的目的在这里写出来。)
<H3>2.4.4 - <A name=2.4.4>控制结构</A></H3>
<P><B>if</B>、 <B>while</B>、以及 <B>repeat</B> 这些控制结构符合通常的意义,而且也有类似的语法: <PRE> stat ::= <B>while</B> exp <B>do</B> block <B>end</B>
stat ::= <B>repeat</B> block <B>until</B> exp
stat ::= <B>if</B> exp <B>then</B> block {<B>elseif</B> exp <B>then</B> block} [<B>else</B> block] <B>end</B>
</PRE>
<P>Lua 也有一个 <B>for</B> 语句,它有两种形式(参见 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.4.5">§2.4.5</A>)。
<P>控制结构中的条件表达式可以返回任何值。 <B>false</B> 和 <B>nil</B> 两者都被认为是假条件。所有不同于 <B>nil</B> 和
<B>false</B> 的其它值都被认为是真(特别需要注意的是,数字 0 和空字符串也被认为是真)。
<P>在 <B>repeat</B>–<B>until</B> 循环中,内部语句块的结束点不是在 <B>until</B>
这个关键字处,它还包括了其后的条件表达式。因此,条件表达式中可以使用循环内部语句块中的定义的局部变量。
<P><B>return</B> 被用于从函数或是 chunk(其实它就是一个函数)中返回值。 函数和 chunk 可以返回不只一个值,所以
<B>return</B> 的语法为 <PRE> stat ::= <B>return</B> [explist1]
</PRE>
<P><B>break</B> 被用来结束 <B>while</B>、 <B>repeat</B>、或 <B>for</B>
循环,它将忽略掉循环中下面的语句段的运行: <PRE> stat ::= <B>break</B>
</PRE>
<P><B>break</B> 跳出最内层的循环。
<P><B>return</B> 和 <B>break</B> 只能被写在一个语句块的最后一句。如果你真的需要从语句块的中间 <B>return</B> 或是
<B>break</B> ,你可以使用显式的声名一个内部语句块。一般写作 <CODE>do return end</CODE> 或是 <CODE>do
break end</CODE>,可以这样写是因为现在 <B>return</B> 或 <B>break</B> 都成了一个语句块的最后一句了。
<H3>2.4.5 - <A name=2.4.5>For 语句</A></H3>
<P><B>for</B> 有两种形式:一种是数字形式,另一种是一般形式。
<P>数字形式的 <B>for</B> 循环,通过一个数学运算不断的运行内部的代码块。下面是它的语法: <PRE> stat ::= <B>for</B> Name `<B>=</B>´ exp `<B>,</B>´ exp [`<B>,</B>´ exp] <B>do</B> block <B>end</B>
</PRE>
<P><EM>block</EM> 将把 <EM>name</EM> 作循环变量。从第一个 <EM>exp</EM> 开始起,直到第二个
<EM>exp</EM> 的值为止,其步长为第三个 <EM>exp</EM> 。更确切的说,一个 <B>for</B> 循环看起来是这个样子 <PRE> for v = <EM>e1</EM>, <EM>e2</EM>, <EM>e3</EM> do <EM>block</EM> end
</PRE>
<P>这等价于代码: <PRE> do
local <EM>var</EM>, <EM>limit</EM>, <EM>step</EM> = tonumber(<EM>e1</EM>), tonumber(<EM>e2</EM>), tonumber(<EM>e3</EM>)
if not (<EM>var</EM> and <EM>limit</EM> and <EM>step</EM>) then error() end
while (<EM>step</EM> > 0 and <EM>var</EM> <= <EM>limit</EM>) or (<EM>step</EM> <= 0 and <EM>var</EM> >= <EM>limit</EM>) do
local v = <EM>var</EM>
<EM>block</EM>
<EM>var</EM> = <EM>var</EM> + <EM>step</EM>
end
end
</PRE>
<P>注意下面这几点:
<UL>
<LI>所有三个控制表达式都只被运算一次,表达式的计算在循环开始之前。这些表达式的结果必须是数字。
<LI><CODE><EM>var</EM></CODE> 、<CODE><EM>limit</EM></CODE> 、以及
<CODE><EM>step</EM></CODE> 都是一些不可见的变量。这里给它们起的名字都仅仅用于解释方便。
<LI>如果第三个表达式(步长)没有给出,会把步长设为 1 。
<LI>你可以用 <B>break</B> 来退出 <B>for</B> 循环。
<LI>循环变量 <CODE>v</CODE> 是一个循环内部的局部变量;当 <B>for</B>
循环结束后,你就不能在使用它。如果你需要这个值,在退出循环前把它赋给另一个变量。 </LI></UL>
<P>一般形式的 <B>for</B>
通过一个叫作叠代器(<EM>iterators</EM>)的函数工作。每次叠代,叠代器函数都会被调用以产生一个新的值,当这个值为 <B>nil</B>
时,循环停止。一般形式的 <B>for</B> 循环的语法如下: <PRE> stat ::= <B>for</B> namelist <B>in</B> explist1 <B>do</B> block <B>end</B>
namelist ::= Name {`<B>,</B>´ Name}
</PRE>
<P><B>for</B> 语句好似这样 <PRE> for <EM>var_1</EM>, ···, <EM>var_n</EM> in <EM>explist</EM> do <EM>block</EM> end
</PRE>
<P>它等价于这样一段代码: <PRE> do
local <EM>f</EM>, <EM>s</EM>, <EM>var</EM> = <EM>explist</EM>
while true do
local <EM>var_1</EM>, ···, <EM>var_n</EM> = <EM>f</EM>(<EM>s</EM>, <EM>var</EM>)
<EM>var</EM> = <EM>var_1</EM>
if <EM>var</EM> == nil then break end
<EM>block</EM>
end
end
</PRE>
<P>注意以下几点:
<UL>
<LI><CODE><EM>explist</EM></CODE> 只会被计算一次。它返回三个值, 一个叠代器函数,一个状态,一个叠代器的初始值。
<LI><CODE><EM>f</EM></CODE>、 <CODE><EM>s</EM></CODE>、 以及
<CODE><EM>var</EM></CODE> 都是不可见的变量。这里给它们起的名字都只是为了解说方便。
<LI>你可以使用 <B>break</B> 来跳出 <B>for</B> 循环。
<LI>循环变量 <CODE><EM>var_i</EM></CODE> 对于循环来说是一个局部变量;你不可以在 <B>for</B>
循环结束后继续使用。如果你需要保留这些值,那么就在循环结束前赋值到别的变量里去。 </LI></UL>
<H3>2.4.6 - <A name=2.4.6>把函数调用作为语句段</A></H3>
<P>为了允许使用可能的副作用,函数调用可以被作为一个语句段执行: <PRE> stat ::= functioncall
</PRE>
<P>在这种情况下,所有的返回值都被舍弃。函数调用在 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5.8">§2.5.8</A>
中解释。
<H3>2.4.7 - <A name=2.4.7>局部变量声名</A></H3>
<P>局部变量可以在语句块中任何地方声名。声名可以包含一个初始化赋值操作: <PRE> stat ::= <B>local</B> namelist [`<B>=</B>´ explist1]
</PRE>
<P>如果有的话,初始化赋值操作的行为等同于赋值操作(参见 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.4.3">§2.4.3</A>)。否则,所有的变量将被初始化为
<B>nil</B>。
<P>一个 chunk 同时也是一个语句块(参见 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.4.1">§2.4.1</A>),所以局部变量可以放在
chunk 中那些显式注明的语句块之外。这些局部变量的作用范围从声明起一直延伸到 chunk 末尾。
<P>局部变量的可见规则在 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.6">§2.6</A> 中解释。
<H2>2.5 - <A name=2.5>表达式</A></H2>
<P>Lua 中有这些基本表达式: <PRE> exp ::= prefixexp
exp ::= <B>nil</B> | <B>false</B> | <B>true</B>
exp ::= Number
exp ::= String
exp ::= function
exp ::= tableconstructor
exp ::= `<B>...</B>´
exp ::= exp binop exp
exp ::= unop exp
prefixexp ::= var | functioncall | `<B>(</B>´ exp `<B>)</B>´
</PRE>
<P>数字和字符串在 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.1">§2.1</A>
中解释;变量在 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.3">§2.3</A>
中解释;函数定义在 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5.9">§2.5.9</A>
中解释;函数调用在 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5.8">§2.5.8</A>
中解释; table 的构造在 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5.7">§2.5.7</A>
中解释;可变参数的表达式写作三个点 ('<CODE>...</CODE>') ,它只能被用在有可变参数的函数中;这些在 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5.9">§2.5.9</A>
中解释。
<P>二元操作符包含有数学运算操作符(参见 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5.1">§2.5.1</A>),比较操作符(参见
<A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5.2">§2.5.2</A>),逻辑操作符(参见
<A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5.3">§2.5.3</A>),以及连接操作符(参见
<A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5.4">§2.5.4</A>)。一元操作符包括负号(参见see
<A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5.1">§2.5.1</A>),取反
<B>not</B>(参见 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5.3">§2.5.3</A>),和取长度操作符(参见
<A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.5.5">§2.5.5</A>)。
<P>函数调用和可变参数表达式都可以放在多重返回值中。如果表达式作为一个独立语句段出现(参见 <A
href="http://www.codingnow.com/2000/download/lua_manual.html#2.4.6">§2.4.6</A>)(这只能是一个函数调用),它们的返回列表将被对齐到零个元素,也就是忽略所有返回值。如果表达式用于表达式列表的最后(或者是唯一)的元素,就不会有任何的对齐操作(除非函数调用用括号括起来)。在任何其它的情况下,Lua
将把表达式结果看成单一元素,忽略除第一个之外的任何值。
<P>这里有一些例子: <PRE> 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() 返回的所有结果
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -