lua使用教程

5.1k 词
文章目录
	</div>
	
	<p>闲来无趣,稍微看了一会lua…</p>

运行

1.命令行运行lua命令,在luashell中执行语句

1
2
3
4
5
zhubenshuli@raspberrypi /var/www/lua_program $ lua
Lua 5.3.1 Copyright (C) 1994-2015 Lua.org, PUC-Rio
> ("hello world!")
hello world!
>

2.使用lua命令直接执行脚本文件

1
2
zhubenshuli@raspberrypi /var/www/lua_program $ lua test.lua
hello world!

3.像shell一样运行

1
2
3
4
5
6
zhubenshuli@raspberrypi /var/www/lua_program $ cat hello.lua
#!/usr/local/bin/lua
print("hello world!")
zhubenshuli@raspberrypi /var/www/lua_program $ sudo chmod +x hello.lua
zhubenshuli@raspberrypi /var/www/lua_program $ ./hello.lua
hello world!

语法

1.注释

1
2
3
4
5


--[[
这是神奇的块注释
--]]

2.变量
lua的变量没有特殊说明全是全局变量,变量前加local关键字的是局部变量。
可以这样访问全局变量(假设变量名为globalVar):

1
2
_G.globalVar
_G["globalVar"]

布尔类型是false的情况只有nilfalse
lua的数字只有double型,64bits

控制语句

while循环

1
2
3
4
5
6
7
8
sum = 0;
num = 1;
while num <= 100 do
sum = sum + num
num = num + 1
end

print("sum =",sum)

if-else分支

1
2
3
4
5
6
7
8
9
10
11
12
age = 50
sex = "male"
if age == 40 and sex == "male" then
print("男人四十一枝花")
elseif age == 60 and sex ~= "female" then
print("old man without country!")
elseif age < 20 then
io.write("too young too simple")
else
local age = io.read()
print("your age is "..age)
end

不等于是~=
字符串的拼接操作符是..
条件语句中的与或非是:and、or、not

for循环

  • 从1加到100

    1
    2
    3
    4
    sum = 0
    for i = 1, 100 do
    sum = sum + i
    end
  • 从1到100的奇数和

    1
    2
    3
    4
    sum = 0
    for i = 1, 100, 2 do
    sum = sum + i
    end

until循环

1
2
3
4
5
sum = 2
repeat
sum = sum ^ 2 -- 幂操作
print(sum)
until sum > 1000

函数

递归

1
2
3
4
function fib(n)
if n < 2 then return 1 end
return fib(n-2) + fib(n-1)
end

闭包

1
2
3
4
5
6
7
8
9
10
11
function newCounter()
local i = 0
return function()
i = i + 1
return i
end
end

cl = newCounter()
print("cl() = "..cl()) -- cl() = 1
print("cl() = "..cl()) -- cl() = 2

1
2
3
4
5
6
7
8
9
10
11
function myPower(x)
return function(y)
return y^x
end
end

power2 = myPower(2)
power3 = myPower(3)

print("power2(4) = "..power2(4)) -- 4的2次方
print("power3(5) = "..power3(5)) -- 5的3次方

函数的返回值
函数可以返回多个值

1
2
3
4
5
function getUserinfo()
return "xqd", "25", "php"
end

name, age, profession = getUserinfo()

Table

table是一个KEY VALUE的数据结构:
zhubenshuli = {name="xqd", age=25, handsome=false}
遍历table

1
2
3
for k, v in pairs(zhubenshuli) do
print(k, v)
end

tableCRUD操作:

1
2
3
4
zhubenshuli.github = "https://github.com/zhubenshuli"
zhubenshuli.name = nil
zhubenshuli.handsome = true
age = zhubenshuli.age

也可以这样定义table
t = {[20]=100, ['name']="xqd", [3.14]="PI"}
可以这样访问:t[20]t["name"]t[3.14]

数组:arr = {10, 20, 30, 40, 50}
等价于:arr = {[1]=10, [2]=20, [3]=30, [4]=50, [5]=50}
也可以定义成不同类型的数组:arr = {"string", false, 34, function() print("xqd is me!") end}
数组中的函数可以这样调用:arr[4]()
数组中的下标是从1开始的

1
2
3
for i=1, #arr do
print(arr[i])
end

MetaTable和MetaMethod

MetaTable主要用来做一些类似于C++重载操作符式的功能。
比如,有两个分数:

1
2
fraction_a = {numeractor=2, denominator=3}
fraction_b = {numeractor=4, denominator=7}

要实现两个分数的相加:2/3+4/7,就要动用MetaTable

1
2
3
4
5
6
7
fraction_op = {}
function fraction_op.__add(f1, f2)
ret = {}
ret.numeractor = f1.numeractor*f2.denominator+f1.denominator*f2.numeractor
ret.denominator = f1.denominator*f2.denominator
return ret
end

为之前定义的两个table设置MetaTable

1
2
setmetatable(fraction_a, fraction_op)
setmetatable(fraction_b, fraction_op)

最后就可以实现两个table相加了:

1
fraction_c = fraction_a + fraction_b

__addMetaMethod,这是lua内建约定的,还有其它如下的MetaMethod

MetaMethod 对应表达式
__add(a,b) a+b
__sub(a,b) a-b
__mul(a,b) a*b
__div(a,b) a/b
__mod(a,b) a%b
__pow(a,b) a^b
__unm(a) -a
__concat(a,b) a..b
__len(a) #a
__eq(a,b) a==b
__lt(a,b) a < b
__le(a,b) a<=b
__index(a,b) a.b
__newindex(a,b,c) a.b=c
__call(a, …) a(…)

“面向对象”

__index这个重载,主要是重载了find key的操作。
如果我们有两个对象ab,想让b作为aprototype只需要:
setmetatable(a, {__index = b})
实例:用一个Window_Prototype的模板加上__indexMetaMethod来创建另一个实例:

1
2
3
Window_Prototype = {x=0, y=0, width=100, height=100}
MyWin = {title="hello"}
setmetatable(MyWin, {__index = Window_Prototype})

于是MyWin就可以访问xwidth等等了。
注:当表要索引一个值如table[key],lua会先在table本身中查找key的值,如果没有并且这个table存在一个带_index属性的MethTable,则lua会按照__index所定义的函数逻辑去查找。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Person = {}

function Person:new(p)
local obj = p
if(obj == nil) then
obj = {name="xqd", age=25, handsome=true}
end
self.__index = self
return setmetatable(obj, self)
end

function Person:toString()
return self.name.." : "..self.age.." : "..(self.handsome and "handsome" or "ugly")
end

从上面我们可以看到一个new方法和toString方法,其中
1.self就是PersonPerson:new(p)相当于Person.new(self,p)
2.new方法的self.__index=self的意图是怕self被扩展后改写,让其保持原样
3.setmetatable这个函数返回的是第一个参数的值
可以这样调用:

1
2
3
4
5
me = Person:new()
print(me:toString())

kf = Person:new({name="King's fucking", age=80, handsome=false})
print(kf:toString())

继承如下:

1
2
3
4
5
6
7
8
9
10
11
Student = Person:new()

function Student:new()
newObj = {year=2015}
self.__index = self
return setmetatable(newObj, self)
end

function Student:toString()
return "Student:"..self.name..", "..self.year
end

模块

可以直接使用requite("model_name")来载入别的lua文件,文件的后缀名是.lua,载入的时候就直接执行那个文件了。
注意:
1.require函数,载入同样的lua文件时,只有第一次的时候去执行,后面相同的都不执行了。
2.如果要让每一次文件载入都执行的话,可以使用dofile("model_name.lua")函数
3.载入后在需要的时候执行,可以使用loadfile函数。如:

1
2
3
4
local hello = loadfile("model_name.lua")
...
...
hello()

正常用法如下:
mymod.lua内容如下:

1
2
3
4
5
6
7
8
9
10
11
local xqdModel = {}

local function getname()
return "xqd"
end

function xqdModel.Greeting()
print("hello, my name is "..getname())
end

return xqdModel

然后就可以这样使用:

1
2
local xqd_model = require("mymod")
xqd_model.Greeting()