Lua简要笔记。
Hello, World
直接在命令行运行(前提lua已加入环境变量中):
>>print(“Hello, World!”)
print语句写在文件中,如hello.lua, print(“Hello, World!”)保存
在文件所在目录打开命令行,然后再执行命令:lua hello.lua
lua还提供一个e选项可以直接在命令行中执行lua代码:
lua -e “print(‘Hello, World!’)”
lua也可以像c语言一样支持命令行参数,然后在lua中捕获这些参数值
参数值都存在一个arg的全局表中1
2
3
4-- 直接输出包括脚本文件名称在内的所有参数
for i = 0, table.getn(arg) do
print(arg[i])
endlua test.lua arg1 arg2 arg3
注释
单行注释,二个连续的中划线”–”,一行内二个中划线后的内容就被认为是注释内容
1
-- single line comment in lua
多行注释,以”–[[“开头,然后以”]]”结尾的部分都会被认为是多行注释(块注释)
1
2
3
4--[[
muilti line comment in lua
by bugcode
]]变量定义
全局变量
在lua中因为是脚本语言,不需要声明,需要变量的时候直接定义使用(就是需要的时候拿过来用)
不需要类型关键字等信息,定义的这些变量都是全局变量。
1
2
3
4--未加local标识符,下面定义的都是全局变量
var_def_num = 12 --定义了一个数值变量
var_def_str = 'string' --定义了一个字符串
var_def_bool = false --定义了一个布尔类型局部变量
如果你想定义一下局部变量,需要在变量前加”local”关键字。应该尽可能使用局部变量,因为一来可以避免冲突,二来局部变量访问速度快于全局变量
1
local var_def_loc_num = 20 --定义了一个局部变量
各种类型
可以通过lua的内置函数type来得知每个变量的类型,type函数返回一个字符串
1 | print(type("string"))--string |
nil
nil表示没有使用过的变量,一个使用过的全局变量赋值为nil即表示删除了这个变量。
nil是值,也是一个类型,可以直接给一个变量赋值为nil。
1
var_global = nil
布尔类型
false与true,只有false与nil表示false,其他的所有都表示为true(包括数值0与空字符串””)
也可以直接给变量赋值false或者true。
1
local boolean = false
数值类型
在lua中数值只有一种,就是c语言中的double,并不会有浮点数的效率问题,下面的赋值都是合法的
1
2
3
4var_int = 12
var_float = 20.01
var_math = 1.34e12
var_math_neg = 0.12e-12字符串
定义与使用,lua中比较常用的一种数据类型,可以处理_量_很大的字符串,定义的方式就是使用单引号或者双引号括起来都可以。
1
2var_string_dou_qt = "string in lua with double quot"
var_string_sig_qt = 'string in lua with single quot'转义
在lua中也如c语言中,支持一些转义字符,如换行,响铃之类,如下:
| 符号 | 含义 |
| :–: | :—-: |
| \a | 响铃 |
| \b | 退格 |
| \f | 换页 |
| \n | 换行 |
| \r | 回车 |
| \t | 横向制表 |
| \v | 纵向制表 |
| \ | 转义 |
| \” | 双引号 |
| \’ | 单引号 |
| [] | 左,右中括号 |lua中也支持使用\xxx的方式表示字符(x为一个十进制的数字),如\049就是数字1,\98就是小写字母b。
有些情况就是使用一些大段的字符串,而且显示的时候需要换行,这样就会在单行的字符串中出现多个\n之类的转义字符出现
可能美观上不太好看,lua提供了另一个字符串的表示方法,就是用”[[“与”]]”将要显示或者处理的字符串括起来,那么二个[[与]]之间的字符串就会是保持原样。1
2
3
4var_string_in_bracket = [[
keep origion style string in lua
that use double square bracket
]]字符串连接
先提一下字符的连接是”..”使用二个句点连接字符串:
1
2var_str = "prefix_string"
print(var_str .. "_middle_string" .. "_suffix_string")输出的就是_prefix_string_middle_string_suffix_string_。
lua中的字符串是定义后是不可修改的(类似于c语言中的字符串字面量),但是可以用一个新的字符串变量接收修改后的字符串。这里的字符串也是不需要手动分配内存与释放内存的,都是lua自动分配与释放的。
1
2
3
4
5var_str = "string for lua"
--这里并没有改动var_str的内容,而是返回了一个新的字符串,被str_res接收
var_res = string.gsub(var_str, "lua", "python")
print("var_res: " .. var_res)
print("var_str: " .. var_str)字符串与数值的互转
lua会自动的在字符串与数值类型间相互转换,比如对一个字符串进行数值上才有的操作时,这时字符串就会转为数值,会在期望一个数值的地方将字符串转为数值,如果期望数值的地方不是数值或者转不成数值就会报错。同理,在期望一个字符串的地方遇到了数值,就会把数值转换成字符串。
1
2
3
4
5-- 此时"25"会转换为数值25,var_rst就是37
var_rst = "25" + 12
print("12" * "4")--输出48
print("12" * "str")--报错,期望str是一个数值然后与12做乘法,但是str无法转换成数值,报错!
print(100 .. 200) -- 100200,数字后的连接符号前要有空格,不然可能会被解释错。
函数
在lua中函数也是一个类型,也就是表示,函数在lua可以当做参数,可以赋值给变量,可以做为函数的返回值
定义方法,function关键字,end结束
1 | function lua_function(param) |
Userdata和Threads
userdata是c中的定义的新数据类型,它可以直接将c中的数据放在lua的变量中,并且userdata在lua中除了赋值与相等操作并没有其他预定义好的操作,threads是协同的时候需要用到的。
表达式
算术运算符
乘方操作符^,其他与C语言一致,对于减号,如果是二元运算(有二个操作数),表示减法操作,如果一元操作(只有一个操作数)表示取负数,这些运算符的操作数都是实数,也就是上文类型中的数值类型。
关系运算符
不等于操作等是~=,其他与C语言一致,除了不等于其他都与c语言相同,进行相等比较的时候,在lua中比较二个操作数的值,如果值类型不同,那么lua认为二个值不同,对于userdata,table,function三种数据,lua则是通过比较引用来确定二个对象是否相等,也就是说,单单内部的值相等是不够的,要二个操作数表示的是同一个对象,才相等。
“10” == 10 这是不同类型的二个值,这个表达式生成false
10 > “2” 类似这种数值与字符串的大小比较,lua会直接报错
逻辑运算符
| 符号 | 作用 |
| :–: | :–: |
| and | 与 |
| or | 或 |
| not | 非 |上文布尔类型的时候说过,lua中除了nil和false是false,其他都是true,逻辑运算也就与c语言相同了
有二个技巧可以用,因为在lua没有三元运算符,可以这样实现1
2-- x ? y : z
(x and y) or z还有一种常用的变量非nil测试并赋值
1
2
3
4
5x = x or val
--等价于
if x == nil then
x = val
end连接运算
字符串的时候提到过了,二个句点,用于连接二个字符串,如果操作数是数值类型,则会把数值转换为字符串,但是数值使用连接符号的时候空格是必须的,以防解释错连接符作用
构造表
由构造器(constructor)来构造表,最简单的表的构造
1 | tbl = {} -- 这就构造了一个空的表 |
也可以直接像c语言的数组初始化一样定义的同时初始化表1
halfy_month_tbl = {"1", "2", "3", "4", "5", "6"}
这就相当于把”1”放在了halfy_month_tbl[1]中,依次类推(lua中索引从1开始,而不是从0开始)
还可以使用类似于键值的方式来初始化表1
rect_tbl = {wid = 10, hgt = 20, name = "Rectangle"}
此时访问对应的表中的数据,需要使用标签索引,rect_tbl[“wid”] -> 10, rect_tbl[“name”] -> “Rectangle”
也可以使用rect_tbl.hgt来访问hgt域
而且我们可以随时向表中添加或者删除任何类型的域,构造器只是在初始化的时候起作用1
2
3
4
5
6
7
8
9
10
11--初始化一个表
ext_tbl = {x = 10, y = 15, desc = "extension"}
tmp_tbl = {is_add = false, z = 10.01}
--向ext_tbl中添加一个域,内容是一个表
ext_tbl["ext"] = tmp_tbl
ext_tbl[1] = "test_area"
--删除ext_tbl的一个域
ext_tbl["x"] = nil
print(ext_tbl[1]) -- "test_area"
print(ext_tbl.ext["z"]) -- 10.01
print(ext_tbl.x) -- nil
因为每次使用构造器的时候都产生一个新的表,可以用这个特性生成一个链表1
2
3
4
5
6
7
8
9
10
11linked_list = nil
--构造链表
for i = 1, 20, 2 do
linked_list = {n = linked_list, v = i}
end
--反序输出
tmp = linked_list
while tmp do
print(tmp.v)
tmp = tmp.n
end
表也可以在初始化的时候同时使用没有域名字与有域名字的1
2
3
4
5
6
7tbl = {x = 10, y = 30, "first"}
print(tbl.x) -- 10
print(tbl[1]) -- "first"
--还可以使用嵌套表的结构
init_tbl = {name = "table", area = 10, {a = 1, b = 2}, {is_loop = true, has_prefix = false}}
print(init_tbl[1].a) -- 1
print(init_tbl[2].has_prefix) --false
我们不能使用负索引来初始化,还有一种更通用的方式来初始化字符串索引的表,使用[exp] (中括号加字符串的方式来表示字符串索引)1
2week_tbl = {["mon"] = 1, ["tues"] = 2, ["wed"] = 3, ["thu"] = 4, ["fri"] = 5, ["sat"] = 6, ["sun"] = 7}
print(week_tbl["mon"]) -- 1
表初化的最后一个域后的逗号是可选的,可加可不加,加上是为了经后的扩展,逗号也可以用分号(;)来替代,通过的做法是
同类型的用逗号,不同类型间的用分号分隔1
type_tbl = {num = 10, 100; str = "string", "value"; boolean = false, true}
语法
赋值语句
单变量赋值,像c语言一样,等号左边是变量右边是表达式
1
2assign_var = 100
var_str = "pre" .. "str"多变量赋值,左边是用逗号分隔开的一个变量的列表,右边是表达式的列表,如果变量数目多于表达式个数,则后面的变量是nil,如果表达式数目多于变量数目,那么多的表达式就会丢弃:
1
2
3x, y, z = 100, false, "multi" .. " assignment"
a, b = 10, 20, 30 --30会被丢弃
k, l, m = 1, 2 -- m --> nil交换变量,在lua中交换二个变量非常简单,反序赋值就可以了
1
2x = 10; y = 20
x, y = y, x -- 完成了交换 x --> 20, y --> 10流程控制语句
if..else
形式是这样的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19x = nil
--单个的if
if not x then
x = 100
end
--if与else
if x == 100 then
x = x - 10
else
x = x + 10
end
--if..elif..else
if x == 100 then
print(x)
elif x == 10 then
print("x == 10")
else
print("else condition")
endwhile
形式是
1
2
3
4
5
6index = 1
fact = 1
while i < 10 do
fact = fact * i
end
print(fact)repeat..until
类似于c语言的do..while
1
2
3
4
5
6
7
8i = 1
sum = 0
-- compute 1 to 10 summary
repeat
sum = sum + i
i = i + 1
until i > 9
print(sum)for循环
普通for循环
1
2
3
4
5
6
7
8--1 to 20 with 2 increament
_start = 1 --起始值
_end = 20 -- 结束值,由start与end构成的
_step = 2 -- 每次循环i的增量,可为负值
-- !此处的i是局部变量,只在for循环的作用域内起作用
for i = _start, _end, _step do
print(i)
end范型for循环, 通过ipairs与pairs迭代器
1
2
3
4
5
6
7
8
9--输出数组中所有的数值
tbl = {1, 3, 5, 6; false; "end"}
for i, v in ipairs(tbl) do
print(v)
end
--输出表中的key
for i in pairs(tbl) do
print(tbl[i])
endipairs 只能迭代到表中非整数的key为止,并且不返回nil,只返回0,遇到nil就退出
pairs 能迭代表中所有的key,并且能返回nil1
2
3
4
5
6
7
8
9tbl_es = {[1] = "11", [2] = "22", [5] = "55", ["six"] = false}
--只输入11与22,因为迭代到3的时候是nil,遇到nil就直接跳出了
for i, v in ipairs(tbl_es) do
print(v)
end
--遍历所有的表中的key
for i in pairs(tbl_es) do
print(tbl_es[i])
endbreak与return
break作用与c语言相同都是跳出循环的,在lua中包括while, repeat..while, for循环
return是从函数中返回值用的,一般的时候都是出现一个语句块的最后,但是如果有需要在中间需要return的时候需要使用do..end括起来形成一个语句块1
2
3
4
5
6
7
8
9function return_test()
for i = 1, 100, 2 do
if i == 13 then
do return end
else
print(i)
end
end
end