Programming in LUA中文版
转自csdn的BLOG(译者应该是ouyangbuxiu)
序(Preface):
当前很多程序语言致力于帮你编写成千上万行的代码,所以这种类型的语言提供包、命名空间、复杂的类型系统、无数的结构、上千页的文档需要学习。
Lua并不帮你编写大量的代码的程序,相反,Lua帮你用少量的代码解决问题。为实现这个目标,像其他语言一样Lua依赖于其可扩展性。然而与其他语言不同的是,不仅用Lua编写的软件易于扩展,其他语言比如c/c++编写的软件也很容易扩展。
一开始,Lua就被设计成很容易和传统的c/c++整合的语言。这种语言的二元性带来很大的好处。Lua是一个小巧简单的语言,因为Lua不致力于做c语言已经做得很好的领域,比如:性能,底层操作以及与第三方软件的接口。Lua依赖于c去做完成这些任务。Lua所提供的机制是c不善于的:高级语言、动态结构、简洁、易于测试和调试。正因为如此,Lua具有很好的安全保证,自动内存管理,容易处理字符串以及其他大小动态改变的数据。
Lua不仅是一种易于扩展的语言,也是一种易整合语言(glue
language);Lua支持基于组件的软件开发方法,我们可以将一些已经存在的高级组件整合在一起实现一个应用。一般情况下,组件使用像c/c++的静态的语言编写。Lua是我们整合各个组件的粘合剂。通常情况下,组件(或对象)表现为具体的在程序开发过程中很少变化的、占用大量CPU时间的决定性的程序,比如窗口部件和数据结构。对那种在产品的生命周期内变化很多的应用使用Lua可以方便的适用变化。除了作为整合语言外,Lua自身也是一个功能强大的语言。Lua不仅可以整合组件,还可以编辑组件甚至完全使用Lua创建组件。
除了Lua外,还有很多类似的脚本语言,比如: Perl, Tcl, Ruby, Forth, Python;下面这些特征是Lua特有的:
可扩展性:Lua的扩展性非常卓越,以至于很多人把Lua当作一个搭建领域语言的工具(注:比如游戏脚本)。Lua被设计为易于扩展的,可以通过Lua代码或者c代码扩展,Lua的很多功能都是通过外部库来扩展的。Lua很容易与c/c++,java,fortran,Smalltalk,Ada,以及其他脚本语言接口。
简单:简单,小巧;内容少但功能强大,这使得Lua易于学习,很容易实现一些小的应用。他的完全发布版(代码、手册以及某些平台的二进制文件)一张软盘就可以装得下。
高效率:Lua有很高的执行效率,统计表明Lua是目前平均效率最高的脚本语言。
平台无关:Lua几乎可以运行在所有我们听过的系统上,NextStep, OS/2, PlayStation II (Sony), Mac OS-9
and OS X, BeOS, MS-DOS, IBM mainfram
es, EPOC, PalmOS, MCF5206eLITE
Evaluation Board, RISC OS,所有的windows和Unix;Lua不是使用条件编译实现平台无关,而是完全使用ANSI
(ISO) C,这意味着只要你ANSI C编译器你就可以编译并使用Lua。
Lua大部分强大的功能来自于他的类库,这并非偶然。Lua的长处之一是可以通过新类型和函数扩展。动态类型检查最大限度允许多态,自动内存管理简化调用接口,因为这样不需要关心谁来分配内存谁来释放内存,也不需要担心溢出。高级函数和匿名函数可以接受高级参数,使函数更通用。
Lua安装可以指定标准库的一个子集。当在一个限制严格的环境下安装Lua时,认真选择你需要的类库是明智的。如果环境限制非常严格,可以很容易的到类库源代码目录下,修改源代码,保留你需要的函数即可。记住:Lua是很小的(即使加上全部的标准库)并且在大部分系统下你可以不用担心的使用全部的功能。
Lua的使用者:
Lua使用者分为三大类:使用Lua嵌入到其他应用中的、独立使用Lua的、Lua和C混合使用的。
第一:很多人使用Lua嵌入在应用中,比如CGILua (搭建动态网页) 、 LuaOrb (访问 CORBA 对象).
这些类型的应用使用Lua-API注册新函数,创建新类型,通过配置Lua就可以改变应用宿主语言的行为。通常,这种应用的使用者并不知道Lua是一种独立的语言。例如:CGILua用户一般会认为Lua是一中用于Web的语言。
第二:作为一种独立运行的语言,Lua也是很有用的,主要用于文本处理或者只运行一次的小程序。这种应用Lua主要使用它的标准库实现,标准库提供模式匹配和其他一些字串处理的功能。我们可以这样认为:Lua是对文本处理领域的嵌入式语言。
第三:还有一些使用者使用其他语言开发,把Lua当作库使用。这些人大多使用c语言开发,但使用Lua建立简单灵活的易于使用的接口。
本书面向以上三类读者。书的第一部分阐述了语言的本身,展示语言的潜在功能。我们讲述了不同的语言结构,并用一些例子展示如何解决实际问题。这部分既包括基本的语言的控制结构,也包括高级的迭代子和协同。
第二部分重点放在Lua特有的数据结构-tables,讨论了数据结构、持久性、包、面向对象编程,这里我们将看到Lua的真正强大之处。
第三部分介绍标准库。每个标准库一章:数学库,table库,string库,I/O库,OS库,Debug库。
最后一部分介绍了Lua和c接口的API,这部分介绍在c语言中开发应用而不是Lua中,对于那些打算将Lua嵌入到c/c++中的读者可能会对此部分更感兴趣。
其他资源:
参考手册是必备的,如果你真得想学一门
语言,本书和Lua手册互为补充,手册描述语言本身,他不会告诉你语言的数据结构也不会举例说明,但手册是Lua的权威文档,可以得到手册的内容。
---Lua用户社区,提供了一些第三方包和文档。
www.inf.puc-rio.br/~roberto/book/ --本书的更新勘误表,代码和例子。
另外本书针对Lua 5.0,如果你的版本不同,请查阅Lua手册或者版本间的差异。
约定:
1.字符串使用双引号,比如"literal strings";单字符使用单引号,比如'a';模式串也是用单引号,比如'[%w_]*'。
2.符号 --> 表示语句的输出或者表达式的结果:
print(10) --> 10
13 + 3 --> 16
3.符号<-->表示等价,即对于Lua来说,this 写和that 写没有区别。
this <--> that
关于本书:
开始打算写这本书是1998年冬天(南半球),那时候Lua版本是3.1;2000年v4.0;2003年v5.0;Lua的变化给本书带来很大的冲击,很多章节被改写或重写,另外一些章节倍增加进来。
本书的完成必须服从语言的变化,本书在这个时候完成的原因:1.Lua
5.0是一个成熟的版本。2.语言变得越来越大,超出了最初本书的目标。另外一个原因是我想将Lua介绍给大家让更多的人了解Lua。
感谢:
在完成本书的过程中,很多人给了我极大的帮助,人名列表:xxxxxx
谢谢他们所有人。
2.Types and Values
Lua是动态类型语言,变量不要类型定义.Lua中有8个基本类型:nil, boolean, number, string, userdata,
function, thread, and table.
print(type("Hello world")) --> string
print(type(10.4*3)) --> number
print(type(print)) --> function
print(type(type)) --> function
print(type(true)) --> boolean
print(type(nil)) --> nil
print(type(type(X))) --> string
变量没有预定义的类型,每一个变量都可能包含任一种类型的值.
print(type(a)) --> nil (`a' is not initialized)
a = 10
print(type(a)) --> number
a = "a string!!"
print(type(a)) --> string
a = print -- yes, this is valid!
a(type(a)) --> function
注意上面最后两行,我们可以使用function像使用其他值一样使用.一般情况下同一变量代表不同类型的值会造成混乱,最好不要用,特殊情况下可以带来便利,比如nil.
2.1 nil:Lua中特殊的类型,给全局变量负nil可以删除该变量.
2.2
booleans:两个取值false和true.但要注意Lua中所有的值都可以作为条件.在控制结构的条件中除了false和nil为假,其他值都为真.所以Lua认为0和空串都是真.
2.3
numbers:表示实数,Lua中没有整
数.一般有个错误的看法CPU运算符点数比整数慢.事实不是如此,用实数代替整数不会有什么误差(除非数字大于100,000,000,000,000).Lua的numbers可以处理任何长整数不用担心误差.你也可以在编译Lua的时候使用长整型或者单精度符点型代替numbers.数字常量的例子:
4 0.4 4.57e-3 0.3e12 5e+20
2.4 lua 是8位字节,所以字符串可以包含任何数值字符,包括嵌入的0。
这意味着你可以存储任意的2进制数据在一个字符串里.Lua中字符串是不可以修改的,你可以创建一个新的变量存放你要的字符串,如下:
a = "one string"
b = string.gsub(a, "one", "another") -- change string parts
print(a) --> one string
print(b) --> another string
string和其他对象一样,Lua自动进行内存分配和释放,一个string可以只包含一个字母也可以包含一本书,Lua可以高效的处理长字符串,1M的string在Lua中是很常见的.
可以使用单引号或者双引号表示字符串
a = "a line"
b = 'another line'
为了风格统一,最好使用一种,除非两种引号嵌套情况.对于字符串中含有引号的情况还可以使用转义
符来表示.Lua中的转义序列有:
a bell
back space
f form feed
newline
carriage return
horizontal tab
v vertical tab
\ backslash
" double quote
' single quote
[ left square bracket
] right square bracket
例子:
> print("one line
next line
"in quotes", 'in quotes'")
one line
next line
"in quotes", 'in quotes'
> print('a backslash inside quotes: '\'')
a backslash inside quotes: ''
> print("a simpler way: '\'")
a simpler way: ''
还可以在字符串中使用ddd(ddd为三位十进制数字)方式表示字母.
"alo
123"" 和 '97lo104923"'是相同的
还可以使用[[...]]表示字符串.这种形式的字符串可以包含多行,可以嵌套,不会解释转义序列,如果第一个字符是换行符会被自动忽略掉.这种形式的字符串用来包含一段代码是非常方便的.
page = [[
<HTML>
<HEAD>
<TITLE>An HTML Page</TITLE>
</HEAD>
<BODY>
<A HREF="">Lua</A>
[[a text between double brackets]]
</BODY>
</HTML>
]]
io.write(page)
运行时,Lua会在string和numbers之间自动进行类型转换,当一个字符串使用算术操作符时,string会被转成数字.
print("10" + 1) --> 11
print("10 + 1") --> 10 + 1
print("-5.3e - 10"*"2") --> -1.06e-09
print("hello" + 1) -- ERROR (cannot convert "hello")
反过来,当Lua期望一个string而碰到数字时,会将数字
转成string .
print(10 .. 20) --> 1020
..在Lua中是字符串连接符,当在一个数字后面写..时必须加上空格防止被解释错.
尽管字符串和数字可以自动转换,两者是不同的,像 10 ==
"10"这样的比较永远都是错的.如果需要显式将string转成数字可以使用函数tonumber(),如果string不是正确的数字该函数返回nil.
line = io.read() -- read a line
n = tonumber(line) -- try to convert it to a number
if n == nil then
error(line .. " is not a valid number")
else
print(n*2)
end
反之,可以调用tostring()将数字转成字符串,这种转换一直有效:
print(tostring(10) == "10") --> true
print(10 .. "" == "10") --> true
2.5 tables
写网页用什么语言Lua的tables实现了关联数组,关联数组指不仅可以通过数字检索数据,还可以通过别的类型的值检索数据.Lua中除了nil外的类型都可以作为tables的索引下标.tables是Lua主要的也是唯一的数据结构,我们可以通过他实现传统数组,
符号表, 集合, 记录(pascal), 队列,
以及其他的数据结构.Lua的包也是使用tables来描述的,io.read意味着调用io包中的read函数,对Lua而
言意味着使用字符串read作为key访问io表.
Lua中tables不是变量也不是值而是对象.你可以把tables当作自动分配的对象,程序中只需要操纵表的引用(指针)即可.Lua中不需要声明表,使用最简单的{}表达式语句即可创建表.
a = {} -- create a table and store its reference in `a'
k = "x"
a[k] = 10 -- new entry, with key="x" and value=10
a[20] = "great" -- new entry, with key=20 and value="great"
print(a["x"]) --> 10
k = 20
print(a[k]) --> "great"
a["x"] = a["x"] + 1 -- increments entry "x"
print(a["x"]) --> 11
表是匿名的,意味着表和持有表的变量没有必然的关系.
a = {}
a["x"] = 10
b = a -- `b' refers to the same table as `a'
print(b["x"]) --> 10
b["x"] = 20
print(a["x"]) --> 20
a = nil -- now only `b' still refers to the table
b = nil -- now there are no references left to the table
当程序中不再引用表时,这个表将被删除,内存可以重新被利用.表可以使用不同的索引类型存储值.索引大小随着表中元素个数增加而增加.
a = {} -- empty table
-- create 1000 new entries
for i=1,1000 do a = i*2 end
print(a[9]) --> 18
a["x"] = 10
print(a["x"]) --> 10
print(a["y"]) --> nil
最后一行,表对应的域没有被初始化所以为nil,和全局变量一样,Lua的全局变量存储正是使用表来存储的.
可以使用域名作为索引下表访问表中元素,Lua也支持a.name代替a["name"],所
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论