本文对Lua的基础知识做一些简介,帮助读者入门。
一、基本变量
Lua的最常见变量类型有:nil,number,string,boolean。
和python类似,Lua也是一种弱类型的语言。变量的类型可以随意更改,不会报错。
和很多编程语言不同,在Lua里,即使该变量从未被声明和初始化,调用它也不会出错,只是会返回nil。
lua
b = 4.5
c = "I love bad muslim"
d = true
print("a=", a) --even if a non-existing variable is called, no error is triggered. Just give nil
print("b=", b) --just number, no int or double
print("c=", c)
print("d=", d)
print("type of a is ", type(a))
print("type of b is ", type(b))
print("type of c is ", type(c))
print("type of d is ", type(d))
输出:
a= nil
b= 4.5
c= I love bad muslim
d= true
type of a is nil
type of b is number
type of c is string
type of d is boolean
变量a未被声明或初始化,所以类型是nil。如果想要返回它的值,也是nil。
另外,通过type函数返回的变量的类型是string(字符串)。
lua
print("type of type is ", type(type(a)))
输出:
type of type is string
二、Lua的常见操作符
Lua里的+,-,*,/,^等常见数学运算符,和大多数编程语言类似,但Lua里没有+=或者++等写法。另外Lua不需要分号结束句子。
以下是Lua中常见的和其他编程语言不同的操作符:
1、注释
Lua注释的前缀是--。
lua
-- The following does not run
2、不等号
Lua里表示"不等于"的符号是~=,和Matlab一样。
lua
neq = 4~=3
print('neq')
输出:
true
3、字符串连接
Lua里,连接两个字符串,使用..。
lua
ssconcat = "Tom's best friend is ".."Jerry"
输出:
Tom's best friend is Jerry
4、字符串长度
Lua里求字符串长度可以在变量前面加#。
lua
print("length of c is ", #c)
输出:
length of c is 17
5、字符串的拼接
字符串的拼接和很多编程语言类似,用%s,%d放在要插入字符的地方。使用函数string.format(),按照以下格式进行字符串拼接。
lua
ssformat = string.format("Both %d and %d are even number", 4, 6)
输出
formatted string: Both 4 and 6 are even number
6、代码块
和C++,Java的{},Python的缩进不同,Lua的代码块表示和Matlab比较类似,也以if,while等表示开始,end表示代码块结束。具体在后面几章会详述。
三、分支结构
Lua的if语句的格式是if ... elseif ... else ... end
lua
g = 4
if g == 4 then
print("g=4")
elseif g == 7 then
print("g=7")
else
print("neither")
end
Lua里没有switch ... case ...的语句
四、循环结构
Lua里有固定次数的for循环,也有条件循环。
1、for循环
for循环,可以让一个变量从起始值到终点值逐步增加。步长默认唯一,也可自定义。
句法为for ... do ... end
lua
for i = 2,5 do --from 2 to 5 step 1. Both start and end are included
print("i=",i)
end
以上语句是i从2到5,步长为1的for循环。
注意:和python的range()不同,lua里,最大值和最小值都包括。
所以输出是:
i= 2
i= 3
i= 4
i= 5
也可以步数不为1,例如:
lua
for j = 3,12,3 do --from 3 to 12 step 3
print("j=",j)
end
以上语句是i从3到12,步数为3的循环。
输出是:
j= 3
j= 6
j= 9
j= 12
2、while循环
while循环是一种"当循环"结构,表明在符合某条件时执行循环。
句法为while ... do ... end。
lua
num = 0
while num < 5 do
print("num=",num)
num = num + 1 --Don't use num += 1 or num++
end
该语句表示当num < 5时执行循环。
3、repeat循环
repeat循环是一种"知道循环"结构,表明在符合某条件时退出循环。
句法为repeat ... until ...。注意这里不需要end。
lua
repeat
print("num=",num)
num = num - 1
until num < 0
该语句表示当num < 0时退出循环。
五、函数
1、函数的定义
Lua中的函数也是一个变量,类似Swift里的closure(闭包)。
有两种定义函数的方式:
第一种:
lua
function F1()
print("This is function F1")
end
第二种:
lua
F2 = function()
print("This is function F2")
end
注意,F1可以被当成一个变量。现在运行下列语句:
lua
F1D = F1
此时函数F1D()和F1()一模一样。
2、函数的输入和输出
同样,函数很多时候是需要有输入和输出的。
下面构建一个有4个输入,4个输出的函数:
lua
function getEachVariablePlus1(v1, v2, v3, v4) --a function can have multiple inputs and also multiple outputs
if type(v1) == "number" then
out_v1 = v1 + 1
end
if type(v2) == "number" then
out_v2 = v2 + 1
end
if type(v3) == "number" then
out_v3 = v3 + 1
end
if type(v4) == "number" then
out_v4 = v4 + 1
end
return out_v1, out_v2, out_v3, out_v4
现在运行这个函数:
lua
a, b, c, d = getEachVariablePlus1(3,13,23,"nn")
print(string.format("values of a, b, c, d are %s, %s, %s, %s", a, b, c, d))
显然,v4的类型不是number,所以out_v4不会被赋值。因此,out_v4的输出值为nil。
values of a, b, c, d are 4, 14, 24, nil
那么,如果一个函数没有输出,我把函数输出赋予一个变量,Python,Matlab,C++,Java等都会出错。那么在Lua中呢?
lua
rF1 = F1()
print("The return of F1 is ", rF1)
答案是不会。既然F1()无输出,rF1就被赋予nil。
The return of F1 is nil
同样,如果函数的实际输入参数个数超过了定义的个数,运行时也不会报错。
lua
getEachVariablePlus1(4,6,1,3,8)
最后一个输入8就会被忽略。
如果我函数有多个输出,我只要前几个输出呢?
lua
aq, bq = getEachVariablePlus1(4,6,1,3)
此时函数的前两个输出out_v1和out_v2分别被赋予aq和bq。另外两个输出被舍弃。
那我想要后几个输出呢?答案是把前几个输出用_代替。
lua
_, _, cq, dq = getEachVariablePlus1(4,6,1,3)
此时,函数的后两个输出out_v3和out_v4分别被赋予cq和dq。
不过,如果把函数的运行结果直接放入print,将会打印函数的所有输出
lua
print("return of the function is ", getEachVariablePlus1(4,6,1,3))
输出:
return of the function is 5 7 2 4
3、函数输出函数
不像在C++中函数定义不允许嵌套,在Lua以及Swift等,函数也可以输出另一个函数。
lua
calculator = function(operator)
if operator == '+' then
return function(a,b)
return a+b
end
elseif operator == '-' then
return function(a,b)
return a-b
end
else
return function()
end
end
end
这个函数返回的也是一个函数。
lua
getCalc = calculator('t')
print("getCalc(2,3)=", getCalc(2,3))
输出:
getCalc(2,3)=
因为getCalc是由calculator函数里的分支结构里依据第三种情况给出的,是没有输出的函数,所以getCalc(2,3)是nil。
4、局部变量和全局变量
和大多数常见编程语言不同,Lua中的变量,在没有特别说明时,都是全局变量。
lua
function loc()
gbv = 10
end
loc()
print("gbv, which is a global variable, is now ", gbv)
在该函数中,gbv是全局变量。所以尽管loc()已经运行完毕,gbv仍然存在,且值为10
gbv, which is a global variable, is now 10
但,可以通过关键字local,规定一个变量是局部变量
lua
function loc2()
local lcv = 10
end
loc2()
print("lcv, which is a local variable, is now", lcv)
在该函数中,以local为前缀的lcv是局部变量。一旦loc2()运行完毕,lcv就不再存在,成为nil。
lcv, which is a local variable, is now nil
六、表
在Lua中,表和Python的list一样,每个元素的类型不一定要相同。
Lua中的表用大括号表示。
lua
tab1 = {"Good", 30, nil, "tg", true, nil}
1、表的长度
和字符串类似,表的长度也可用#。
注意:这个用#算出的长度,不包括最后的nil
lua
print("the length of tab1 is ", #tab1)
输出:
the length of tab1 is 5
显然,只计到第五个true为止。
2、表的元素提取
和Python,C++,Swift不同,在Lua中,表的默认索引值和Matlab类似,以1开头。
lua
print("element 2 of tab1 is", tab1[2]) --in Lua, table index starts from 1
print("element 10 of tab1 is", tab1[10]) --even it is out of index, no error will be triggered, just return nil
输出:
element 2 of tab1 is 30
element 10 of tab1 is nil
同样,索引号为10时,虽然超出了表的长度,但不会报错,只返回nil。
3、表的自定义索引
除了Lua给每个元素自动赋予的从1开始的索引值外,也可以自行给元素赋予数字或非数字索引。
lua
Tom = {['job']="sales", ["age"]=45, [5]="really?"}
这里,表Tom有三个索引:'job','age',5。这个表有些类似Python、Swift里的字典。
根据非数字索引提取元素的方式有两种:Tom['job']或者Tom.job,两者等价。但是根据数字索引提取元素的方式只有一种:Tom[5]
lua
print("Tom's job is ", Tom["job"], " and his age is ", Tom.age, " and 5 element is ", Tom[5]) --even the index is string '5', still can not use dot to get element
输出:
Tom's job is sales and his age is 45 and 5 element is really?
4、更改或添加或删除元素
更改元素
更改元素的方法:Tom.age=50
添加元素
添加元素的方法也类似,可以理解为把一个索引对应的元素的值从nil改为非nil值。
如果想附加一个元素到最后一个索引后面,使用table.insert(Tom, 'China')
删除元素
删除元素,如果是依据数字索引值,请用table.remove(Tom, 1),移除第一个元素;也可以用Tom[1] = nil,效果一致。如果是依据非数字索引值,只能用Tom['age'] = nil。
如果运行table.remove(Tom, 'age')则会出错!
5、遍历表中元素
有两种方法遍历表中元素
pairs
pairs函数遍历表中所有的非nil元素。输出索引及其对应的元素。
lua
Linda = {[1] = 'ele1', ['age'] = 20, ['e']=nil}
for i,v in pairs(Linda) do
print('the element ', i, ' of Linda is ', v)
end
输出:
the element 1 of Linda is ele1
the element age of Linda is 20
ipairs
ipairs只遍历索引为数字的元素,从1开始,出现元素值为nil的就停止。
lua
Linda = {[1] = "ele1", ['age'] = 20, ['e']=nil}
for i,v in ipairs(Linda) do
print('the element ', i, ' of Linda is ', v)
end
输出:
the element 1 of Linda is ele1
6、一个Lua自带的表
Lua自带了一个表叫_G。该表包括所有已加载的元素。
lua
function hello()
print("Hello Lua")
end
for i,v in pairs(_G) do
print(i,v)
end
输出:
pairs function: 0x1006ad9ac
select function: 0x1006addac
rawset function: 0x1006add50
print function: 0x1006b63d8
rawget function: 0x1006add00
__lua_objc userdata: 0x140bcbe60
os table: 0x15a60b140
io table: 0x15a60b080
string table: 0x15a60b180
coroutine table: 0x15a60b000
package table: 0x15a60ae00
ipairs function: 0x1006ad774
table table: 0x15a60b040
pcall function: 0x1006ada40
warn function: 0x1006adb8c
loadfile function: 0x1006ad7c8
require function: 0x157b77000
hello function: 0x157b762e0
debug table: 0x15a60b2c0
utf8 table: 0x15a60b280
getmetatable function: 0x1006ad71c
math table: 0x15a60b200
collectgarbage function: 0x1006ad444
type function: 0x1006ae180
rawlen function: 0x1006adc9c
dofile function: 0x1006b64c4
next function: 0x1006ad954
rawequal function: 0x1006adc4c
assert function: 0x1006ad3c4
tostring function: 0x1006ae148
load function: 0x1006ad84c
error function: 0x1006ad6a0
setmetatable function: 0x1006ade68
tonumber function: 0x1006adf0c
_VERSION Lua 5.4
_G table: 0x15a60a580
xpcall function: 0x1006ae1e4