lua手册文档格式.docx
《lua手册文档格式.docx》由会员分享,可在线阅读,更多相关《lua手册文档格式.docx(30页珍藏版)》请在冰豆网上搜索。
Lua是一个大小写敏感的语言:
and是一个保留字,但是And和AND则是两个不同的合法的名字。
一般约定,以下划线开头连接一串大写字母的名字(比如_VERSION)被保留用于Lua内部全局变量。
下面这些是其它的token:
+-*/%^#
==~=<
=>
=<
>
=
(){}[]
;
:
......
字符串既可以用一对单引号引起,也可以是双引号,里面还可以包含类似C的转义符:
'
\a'
(响铃),'
\b'
(退格),'
\f'
(表单),'
\n'
(换行),'
\r'
(回车),'
\t'
(横向制表),'
\v'
(纵向制表),'
\\'
(反斜杠),'
\"
'
(双引号),以及'
\'
(单引号)。
而且,如果在一个反斜杠后跟了一个真正的换行符,其结果就是在字符串中产生一个换行符。
我们还可以用反斜杠加数字的形式\ddd来描述一个字符。
这里,ddd是一串最多三位的十进制数字。
(注意,如果需要在这种描述方法后接一个是数字的字符,那么反斜杠后必须写满三个数字。
)Lua中的字符串可以包含任何8位的值。
包括用'
\0'
表示的零。
只有在你需要把不同的引号、换行、反斜杠、或是零结束符这些字符置入字符串时,你才必须使用转义符。
别的任何字符都可以直接写在文本里。
(一些控制符可以会影响文件系统造成某些问题,但是不会引起Lua的任何问题。
)
字符串还可以用一种长括号括起来的方式定义。
我们把两个正的方括号间插入n个等号定义为第n级正长括号。
就是说,0级正的长括号写作[[,一级正的长括号写作[=[,如此等等。
反的长扩展也作类似定义;
举个例子,4级反的长括号写作]====]。
一个长字符串可以由任何一级的正的长括号开始,而由第一个碰到的同级反的长括号结束。
整个词法分析过程将不受分行限制,不处理任何转意符,并且忽略掉任何不同级别的长括号。
这种方式描述的字符串可以包含任何东西,当然特定级别的反长括号除外。
另一个约定是,当正的长括号后面立即跟了一个换行符,这个换行符就不包含在这个字符串内。
举个例子,假设一个系统使用ASCII码(这时,'
a'
编码为97,换行符编码为10,'
1'
编码为49),下面五种方式描述了完全相同的字符串:
a='
alo\n123"
a="
alo\n123\"
"
\97lo\10\04923"
a=[[alo
123"
]]
a=[==[
alo
]==]
数字常量可以分两部分写,十进制底数部分和十进制的指数部分。
指数部分是可选的。
Lua也支持十六进制整数常量,只需要在前面加上前缀0x。
下面是一些合法的数字常量的例子:
33.03.1416314.16e-20.31416E10xff0x56
注释可以在除字符串内的任何地方是以两横(--)开始。
如果跟在两横后面的不是一个长括号,这就是一个短注释,它的作用范围直到行末;
否则就是一个长注释,其作用范围直到遇到反的长括号。
长注释通常被用来临时屏蔽代码块。
2.2-值与类型
Lua是一种动态类型语言。
这意味着变量没有类型,只有值才有类型。
语言中不存在类型定义。
而所有的值本身携带它们自己的类型信息。
Lua中的所有值都是一致(first-class)的。
这意味着所有的值都可以被放在变量里,当作参数传递到另一个函数中,并被函数作为结果返回。
Lua中有八种基本类型:
nil,boolean,number,string,function,userdata,thread,andtable.Nil类型只有一种值nil,它的主要用途用于标表识和别的任何值的差异;
通常,当需要描述一个无意义的值时会用到它。
Boolean类型只有两种值:
false和true。
nil和false都能导致条件为假;
而另外所有的值都被当作真。
Number表示实数(双精度浮点数)。
(编译一个其它内部数字类型的Lua解释器是件很容易的事;
比如把内部数字类型改作单精度浮点数或长整型。
参见文件luaconf.h。
)String表示一串字符的数组。
Lua是8-bitclean的:
字符串可以包含任何8位字符,包括零结束符('
)(参见§
2.1)。
Lua可以调用(和处理)用Lua写的函数以及用C写的函数(参见§
2.5.8).
userdata类型用来将任意C数据保存在Lua变量中。
这个类型相当于一块原生的内存,除了赋值和相同性判断,Lua没有为之预定义任何操作。
然而,通过使用metatable(元表),程序员可以为userdata自定义一组操作(参见§
2.8)。
userdata不能在Lua中创建出来,也不能在Lua中修改。
这样的操作只能通过CAPI。
这一点保证了宿主程序完全掌管其中的数据。
thread类型用来区别独立的执行线程,它被用来实现coroutine(协同例程)(参见§
2.11)。
不要把Lua线程跟操作系统的线程搞混。
Lua可以在所有的系统上提供对coroutine的支持,即使系统并不支持线程。
table类型实现了一个关联数组。
也就是说,数组可以用任何东西(除了nil)做索引,而不限于数字。
table可以以不同类型的值构成;
它可以包含所有的类型的值(除nil外)。
table是lua中唯一的一种数据结构;
它可以用来描述原始的数组、符号表、集合、记录、图、树、等等。
用于表述记录时,lua使用域名作为索引。
语言本身采用一种语法糖,支持以a.name的形式表示a["
name"
]。
有很多形式用于在lua中创建一个table(参见§
2.5.7)。
跟索引一样,table每个域中的值也可以是任何类型(除nil外)。
特别的,因为函数本身也是值,所以table的域中也可以放函数。
这样table中就可以有一些methods了(参见see§
2.5.9)。
table,function,thread,和(full)userdata这些类型的值是所谓的对象:
变量本身并不会真正的存放它们的值,而只是放了一个对对象的引用。
赋值,参数传递,函数返回,都是对这些对象的引用进行操作;
这些操作不会做暗地里做任何性质的拷贝。
库函数type可以返回一个描述给定值的类型的字符串。
2.2.1-强制转换
Lua提供运行时字符串到数字的自动转换。
任何对字符串的数学运算操作都会尝试用一般的转换规则把这个字符串转换成一个数字。
相反,无论何时,一个数字需要作为字符串来使用时,数字都会以合理的格式转换为字符串。
需要完全控制数字怎样转换为字符串,可以使用字符串库中的format函数(参见string.format)。
2.3-变量
写上变量的地方意味着当以其保存的值来替代之。
Lua中有三类变量:
全局变量,局部变量,还有table的域。
一个单一的名字可以表示一个全局变量,也可以表示一个局部变量(或者是一个函数的参数,这是一种特殊形式的局部变量):
var:
:
=Name
Name就是§
2.1中所定义的标识符。
任何变量都被假定为全局变量,除非显式的以local修饰定义(参见§
2.4.7)。
局部变量有其作用范围:
局部变量可以被定义在它作用范围中的函数自由使用(参见§
2.6)。
在变量的首次赋值之前,变量的值均为nil。
方括号被用来对table作索引:
=prefixexp`[´
exp`]´
对全局变量以及table域之访问的含义可以通过metatable来改变。
以取一个变量下标指向的量t[i]等价于调用gettable_event(t,i)。
(参见§
2.8,有一份完整的关于gettable_event函数的说明。
这个函数并没有在lua中定义出来,也不能在lua中调用。
这里我们把它列出来只是方便说明。
var.Name这种语法只是一个语法糖,用来表示var["
Name"
]:
=prefixexp`.´
Name
所有的全局变量都是放在一个特定luatable的诸个域中,这个特定的table叫作environment(环境)table或者简称为环境(参见§
2.9)。
每个函数都有对一个环境的引用,所以一个函数中可见的所有全局变量都放在这个函数所引用的环境表(environmenttable)中。
当一个函数被创建出来,它会从创建它的函数中继承其环境,你可以调用getfenv取得其环境。
如果想改变环境,可以调用setfenv。
(对于C函数,你只能通过debug库来改变其环境;
参见§
5.9)。
对一个全局变量x的访问等价于_env.x,而这又可以等价于
gettable_event(_env,"
x"
)
这里,_env是当前运行的函数的环境。
(函数gettable_event的完整说明参见§
2.8。
这个函数并没有在lua中定义出来,也不能调用。
当然,_env这个变量也同样没有在Lua中定义出来。
我们在这里使用它们,仅仅只是方便解释而已。
2.4-语句段(Statement)
Lua支持惯例形式的语句段,它和Pascal或是C很相象。
这个集合包括赋值,控制结构,函数调用,还有变量声明。
2.4.1-Chunk(语句组)
Lua的一个执行单元被称作chunk。
一个chunk就是一串语句段,它们会被循序的执行。
每个语句段可以以一个分号结束:
chunk:
={stat[`;
´
]}
这儿不允许有空的语句段,所以'
;
是非法的。
lua把一个chunk当作一个拥有不定参数的匿名函数(参见§
2.5.9)处理。
正是这样,chunk内可以定义局部变量,接收参数,并且返回值。
chunk可以被保存在一个文件中,也可以保存在宿主程序的一个字符串中。
当一个chunk被执行,首先它会被预编译成虚拟机中的指令序列,然后被虚拟机解释运行这些指令。
chunk也可以被预编译成二进制形式;
细节参考程序luac。
用源码形式提供的程序和被编译过的二进制形式的程序是可以相互替换的;
Lua会自动识别文件类型并做正确的处理。
2.4.2-语句块
语句块是一列语句段;
从语法上来说,一个语句块跟一个chunk相同:
block:
=chunk
一个语句块可以被显式的写成一个单独的语句段:
stat:
=doblockend
显式的语句块对于控制变量的作用范围很有用。
有时候,显式的语句块被用来在另一个语句块中插入return或是break(参见§
2.4.4)。
2.4.3-赋值先映射后操作
Lua允许多重赋值。
因此,赋值的语法定义是等号左边放一系列变量,而等号右边放一系列的表达式。
两边的元素都用逗号间开:
=varlist1`=´
explist1
varlist1:
=var{`,´
var}
explist1:
=exp{`,´
exp}
表达式放在§
2.5里讨论。
在作赋值操作之前,那一系列的右值会被对齐到左边变量需要的个数。
如果右值比需要的更多的话,多余的值就被扔掉。
如果右值的数量不够需求,将会按所需扩展若干个nil。
如果表达式列表以一个函数调用结束,这个函数所返回的所有值都会在对齐操作之前被置入右值序列中。
(除非这个函数调用被用括号括了起来;
2.5)。
赋值段首先会做运算完所有的表达式,然后仅仅做赋值操作。
因此,下面这段代码
i=3
i,a[i]=i+1,20
会把a[3]设置为20,而不会影响到a[4]。
这是因为a[i]中的i在被赋值为4之前就被拿出来了(那时是3)。
简单说,这样一行
x,y=y,x
可以用来交换x和y中的值。
对全局变量以及table中的域的赋值操作的含义可以通过metatable来改变。
对变量下标指向的赋值,即t[i]=val等价于settable_event(t,i,val)。
(关于函数settable_event的详细说明,参见§
这个函数并没有在Lua中定义出来,也不可以被调用。
这里我们列出来,仅仅出于方便解释的目的)
对于全局变量的赋值x=val等价于_env.x=val,这个又可以等价于
settable_event(_env,"
val)
这里,_env指的是正在运行中的函数的环境。
(变量_env并没有在Lua中定义出来。
我们仅仅出于解释的目的在这里写出来。
2.4.4-控制结构
if、while、以及repeat这些控制结构符合通常的意义,而且也有类似的语法:
=whileexpdoblockend
=repeatblockuntilexp
=ifexpthenblock{elseifexpthenblock}[elseblock]end
Lua也有一个for语句,它有两种形式(参见§
2.4.5)。
控制结构中的条件表达式可以返回任何值。
false和nil两者都被认为是假条件。
所有不同于nil和false的其它值都被认为是真(特别需要注意的是,数字0和空字符串也被认为是真)。
在repeat–until循环中,内部语句块的结束点不是在until这个关键字处,它还包括了其后的条件表达式。
因此,条件表达式中可以使用循环内部语句块中的定义的局部变量。
return被用于从函数或是chunk(其实它就是一个函数)中返回值。
函数和chunk可以返回不只一个值,所以return的语法为
=return[explist1]
break被用来结束while、repeat、或for循环,它将忽略掉循环中下面的语句段的运行:
=break
break跳出最内层的循环。
return和break只能被写在一个语句块的最后一句。
如果你真的需要从语句块的中间return或是break,你可以使用显式的声名一个内部语句块。
一般写作doreturnend或是dobreakend,可以这样写是因为现在return或break都成了一个语句块的最后一句了。
2.4.5-For语句
for有两种形式:
一种是数字形式,另一种是一般形式。
数字形式的for循环,通过一个数学运算不断的运行内部的代码块。
下面是它的语法:
=forName`=´
exp`,´
exp[`,´
exp]doblockend
block将把name作循环变量。
从第一个exp开始起,直到第二个exp的值为止,其步长为第三个exp。
更确切的说,一个for循环看起来是这个样子
forv=e1,e2,e3doblockend
这等价于代码:
do
localvar,limit,step=tonumber(e1),tonumber(e2),tonumber(e3)
ifnot(varandlimitandstep)thenerror()end
while(step>
0andvar<
=limit)or(step<
=0andvar>
=limit)do
localv=var
block
var=var+step
end
注意下面这几点:
∙所有三个控制表达式都只被运算一次,表达式的计算在循环开始之前。
这些表达式的结果必须是数字。
∙var、limit、以及step都是一些不可见的变量。
这里给它们起的名字都仅仅用于解释方便。
∙如果第三个表达式(步长)没有给出,会把步长设为1。
∙你可以用break来退出for循环。
∙循环变量v是一个循环内部的局部变量;
当for循环结束后,你就不能在使用它。
如果你需要这个值,在退出循环前把它赋给另一个变量。
一般形式的for通过一个叫作迭代器(iterators)的函数工作。
每次迭代,迭代器函数都会被调用以产生一个新的值,当这个值为nil时,循环停止。
一般形式的for循环的语法如下:
=fornamelistinexplist1doblockend
namelist:
=Name{`,´
Name}
for语句好似这样
forvar_1,·
·
var_ninexplistdoblockend
它等价于这样一段代码:
localf,s,var=explist
whiletruedo
localvar_1,·
var_n=f(s,var)
var=var_1
ifvar==nilthenbreakend
注意以下几点:
∙explist只会被计算一次。
它返回三个值,一个迭代器函数,一个状态,一个迭代器的初始值。
∙f、s、以及var都是不可见的变量。
这里给它们起的名字都只是为了解说方便。
∙你可以使用break来跳出for循环。
∙循环变量var_i对于循环来说是一个局部变量;
你不可以在for循环结束后继续使用。
如果你需要保留这些值,那么就在循环结束前赋值到别的变量里去。
2.4.6-把函数调用作为语句段
为了允许使用可能的副作用,函数调用可以被作为一个语句段执行:
=functioncall
在这种情况下,所有的返回值都被舍弃。
函数调用在§
2.5.8中解释。
2.4.7-局部变量声名
局部变量可以在语句块中任何地方声名。
声名可以包含一个初始化赋值操作:
=localnamelist[`=´
explist1]
如果有的话,初始化赋值操作的行为等同于赋值操作(参见§
2.4.3)。
否则,所有的变量将被初始化为nil。
一个chunk同时也是一个语句块(参见§
2.4.1),所以局部变量可以放在chunk中那些显式注明的语句块之外。
这些局部变量的作用范围从声明起一直延伸到chunk末尾。
局部变量的可见规则在§
2.6中解释。
2.5-表达式
Lua中有这些基本表达式:
exp:
=prefixexp
=nil|false|true
=Number
=String
=function
=tableconstructor
=`...´
=expbinopexp
=unopexp
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),和取长度操作符(参见