1:Lua 规范
1.1:程序块(chunk)
lua执行的每段代码,例如一个.lua文件,或在一个交互模式中(在CMD中输入lua代码),都称为一个“程序块”。一个程序块就是一连串的lua语句或命令。
(1)几条连续的lua语句不需要分隔符,如果自己喜欢,也可以用分号来隔开,和其他语言的语法一样。
以下的程序块是完全等价的。
[1]
a = 1
b = a*2
[2]
a = 1;
b = a*2;
[3]
a = 1; b = a*2;
[4]
a = 1 b = a*2
(2)一个程序块可以简单到只包含一条语句,就像”Hello World”,也可以想阶乘的例子一样n长。由多条语句及函数构成。程序块可以是任意大小的。
1.2:词法规范
和大多数语言一样,lua的标识符也是由字母,数字,下划线组成,但不能以数字开头。
需要注意的就是:在lua中,应当避免使用一个下划线开头,后面紧跟一个或多个大写字母(例如”_VERSION” 和全局表”_G”)的标识符这些变量一般是lua中有特殊用途的。我们应该尽量少这样用,避免不必要的麻烦。
1.2.1 lua保留关键字
” “ | ” “ | ” “ | ” “ | ” “ |
---|---|---|---|---|
and | break | do | else | elseif |
end | false | for | function | if |
in | local | nil | not | or |
repeat | return | then | true | until |
while |
1.2.2 lua严格区分大小写
“and”一个保留关键字,但”And”和”AND”是2个完全不同的标识符。
1.2.3 lua注释语法
- [ ] 单行注释
可以在任意地方用2个连字符(–)开始一个注释。该注释一直延伸到一行的结尾。
function()
local a = 1
local b = 2
local c = a + b
print("a = " .. a)
--print("b = " .. b)
print("c = " .. c)
上面的代码块只会输出:a = 1 c = 3,打印的b的代码注释了,不会执行到。
- [ ] 代码注释
以”–[[” 开始,直至”–]]”结束,在这中间的代码块是不起作用的。
--[[
print(10) -- 不起作用(代码块被注释了)
--]]
---[[
print(10) --> 10
--]]
在第一个例子中。最后一行的”–”仍在一个块注释中。
第二个例子中,序列”—[[“只是开始了一个普通的行注释。它的第一行和左和最后一行是2个彼此独立的行注释。
1.3:lua全局变量
在lua中如果在声明变量时没有加上”local”的话,默认就是全局变量,会加进去全局表_G里面。
全局变量不需要声明。只需要将一个值赋予一个全局变量就可以创建。在lua中,访问一个未初始化的变量,不会引发错误,只是访问结果是一个特殊的nil。
print(b) -->打印结果:nil
b = 10
print(b) -->打印结果:10
通常没有必要删除一个全局变量。如果一个变量只有较短的生存周期,那么就应该使用全局变量。但是,如果一定要删除某个全局变量的话,只需要将其赋值为nil
b = nuil
print(b) -->打印结果:nil
2:Lua 类型与值
lua是一种动态类型的语言。在语言中没有类型定义的语法,每个值都“携带”了它自身的类型信息。
在lua中总共有8种基础类型。
- nil 空值
- boolean 布尔型
- number 数字
- string 字符串
- userdata自定义类型
- function 函数
- thread 线程
- table 表
函数type可根据一个值返回其名称。
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
最后一行代码永远返回”string”,不管X这个值的内容,这是因为type函数总是返回一个字符串。
print(type(a)) -->nil(a没有初始化)
a = 10
print(type(a)) -->number
a = "a string"
print(type(a)) -->string
a = print
print(type(a)) -->function
将一个变量用来不同类型,通常会导致代码的混乱,但有时明智的使用这种特性会带来便利。例如,在异常情况下,可以返回一个nil以区别于其他的正常的返回值
2.1:nil(空)
nil是一种类型,它只有一个nil,它的主要功能是用于区别其他的任何值。一个变量在第一次赋值前的默认值是 nil,将 nil 赋予给一个全局变量就等同于删除它。
local num
print(num) -->output : nil
num = 100
print(num) -->output : 100
2.2:boolean(布尔)
boolean类型有2个可选的值:false和true,这与其他的语言是一样的,然而boolean却不是一个条件值的唯一表示方式。在lua中任何值都可以表示一个条件。lua将值false和nil视为“假”,而将除此之外的的值视为“真”,这一点不同其他的语言。在lua中,将数字0和空字符串也都视为“真”。
local a = true
local b = 0
local c = nil
if a then
print("a") -->output:a
else
print("not a") --这个没有执行
end
if b then
print("b") -->output:b
else
print("not b") --这个没有执行
end
if c then
print("c") --这个没有执行
else
print("not c") -->output:not c
end
2.3:number(数字)
Lua中的number用于表示实数。Lua中没有专门的类型表示整数。和 C/C++ 里面的 double 类型很类似,可以使用数学函数 math.floor(向下取整)和 math.ceil(向上取整)进行取整操作。
local order = 3.99
local score = 98.01
print(math.floor(order)) -->output:3
print(math.ceil(score)) -->output:99
2.4:string(字符串)
luaz中有3中标识字符串。
(1)单引号”
local str = 'hello world'
(2)双引号”“
local str = "hello world"
(3)字符串还可以用一种长括号(即[[ ]])括起来的方式定义。 我们把两个正的方括号(即[[ )间插入 n 个等号定义为第 n 级正长括号。 就是说,0 级正的长括号写作 [[ , 一级正的长括号写作 [=[ ,如此等等。 反的长括号也作类似定义;
举个例子,4 级反的长括号写作 ]====] 。 一个长字符串可以由任何一级的正的长括号开始,而由第一个碰到的同级反的长括号结束。 整个词法分析过程将不受分行限制,不处理任何转义符,并且忽略掉任何不同级别的长括号。 这种方式描述的字符串可以包含任何东西,当然本级别的反长括号除外。 例:[[abc\nbc]],里面的 “\n” 不会被转义。
local str1 = 'hello world'
local str2 = "hello lua"
local str3 = [["add\name",'hello']]
local str4 = [=[string have a [[]].]=]
print(str1) -->output:hello world
print(str2) -->output:hello lua
print(str3) -->output:"add\name",'hello'
print(str4) -->output:string have a [[]].
在 Lua 实现中,Lua 字符串一般都会经历一个“内化”(intern)的过程,即两个完全一样的 Lua 字符串在 Lua 虚拟机中只会存储一份。每一个 Lua 字符串在创建时都会插入到 Lua 虚拟机内部的一个全局的哈希表中。 这意味着
1:创建相同的 Lua 字符串并不会引入新的动态内存分配操作,所以相对便宜(但仍有全局哈希表查询的开销)
2:内容相同的 Lua 字符串不会占用多份存储空间
3:已经创建好的 Lua 字符串之间进行相等性比较时是 O(1) 时间度的开销,而不是通常见到的 O(n)。
连接字符串
在lua中连接2个字符串的操作是2个点“..”的操作符。
2.5:table(表)
table类型实现了“关联数组”,关联数组是一种具有特殊索引方式的数组。不仅可以通过整数来索引它,还可以使用字符串或其他类型的值(除了nil)来索引。此外,table没有固定的大小,可以动态地添加任意数量的元素到一个table中。
table的功能用途:
1:基于table可以以一种简单,统一,高效的方式来表示普通数组,符号表,集合,记录,队列,和其他的数据结构。
2:lua也可以通过table来实现模块(module),包(package)和对象(object)。
local corp = {
web = "www.google.com", --索引为字符串,key = "web",
--value = "www.google.com"
telephone = "12345678", --索引为字符串
staff = {"Jack", "Scott", "Gary"},--索引为字符串,
--值也是一个表
100876, --相当于 [1] = 100876,此时索引为数字
--key = 1, value = 100876
100191, --相当于 [2] = 100191,此时索引为数字
[10] = 360, --直接把数字索引给出
["city"] = "Beijing" --索引为字符串
}
print(corp.web) -->output:www.google.com
print(corp["telephone"]) -->output:12345678
print(corp[2]) -->output:100191
print(corp["city"]) -->output:"Beijing"
print(corp.staff[1]) -->output:Jack
print(corp[10]) -->output:360
2.6:function(函数)
在lua中,函数是作为“第一类值”来看待,这表示函数可以存储在变量中,也可通过参数传给其他函数。还可以作为其他函数的返回值。
function func()
{
local x = 20
}
local a = func
print(a()) --> output:20
有名函数实际是上匿名函数对变量赋值。
local a = function()end