lua使用教程
<p>闲来无趣,稍微看了一会lua…</p>
运行
1.命令行运行lua
命令,在lua
的shell
中执行语句1
2
3
4
5zhubenshuli@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
2zhubenshuli@raspberrypi /var/www/lua_program $ lua test.lua
hello world!
3.像shell
一样运行1
2
3
4
5
6zhubenshuli@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
的情况只有nil
和false
lua
的数字只有double型,64bits
控制语句
while循环1
2
3
4
5
6
7
8sum = 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
12age = 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
4sum = 0
for i = 1, 100 do
sum = sum + i
end从1到100的奇数和
1
2
3
4sum = 0
for i = 1, 100, 2 do
sum = sum + i
end
until循环1
2
3
4
5sum = 2
repeat
sum = sum ^ 2
print(sum)
until sum > 1000
函数
递归1
2
3
4function (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
11function newCounter()
local i = 0
return function()
i = i + 1
return i
end
end
cl = newCounter()
print("cl() = "..cl())
print("cl() = "..cl()) -- cl() = 2
1 | function myPower(x) |
函数的返回值
函数可以返回多个值1
2
3
4
5function getUserinfo()
return "xqd", "25", "php"
end
name, age, profession = getUserinfo()
Table
table
是一个KEY VALUE
的数据结构:zhubenshuli = {name="xqd", age=25, handsome=false}
遍历table
:1
2
3for k, v in pairs(zhubenshuli) do
print(k, v)
end
table
的CRUD
操作:1
2
3
4zhubenshuli.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
3for i=1, #arr do
print(arr[i])
end
MetaTable和MetaMethod
MetaTable
主要用来做一些类似于C++重载操作符式的功能。
比如,有两个分数:1
2fraction_a = {numeractor=2, denominator=3}
fraction_b = {numeractor=4, denominator=7}
要实现两个分数的相加:2/3+4/7,就要动用MetaTable
:1
2
3
4
5
6
7fraction_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
2setmetatable(fraction_a, fraction_op)
setmetatable(fraction_b, fraction_op)
最后就可以实现两个table
相加了:1
fraction_c = fraction_a + fraction_b
__add
是MetaMethod
,这是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
的操作。
如果我们有两个对象a
和b
,想让b
作为a
的prototype
只需要:setmetatable(a, {__index = b})
实例:用一个Window_Prototype
的模板加上__index
的MetaMethod
来创建另一个实例:1
2
3Window_Prototype = {x=0, y=0, width=100, height=100}
MyWin = {title="hello"}
setmetatable(MyWin, {__index = Window_Prototype})
于是MyWin
就可以访问x
、width
等等了。
注:当表要索引一个值如table[key]
,lua
会先在table
本身中查找key
的值,如果没有并且这个table
存在一个带_index
属性的MethTable
,则lua
会按照__index
所定义的函数逻辑去查找。
1 | Person = {} |
从上面我们可以看到一个new
方法和toString
方法,其中
1.self
就是Person
,Person:new(p)
相当于Person.new(self,p)
2.new
方法的self.__index=self
的意图是怕self
被扩展后改写,让其保持原样
3.setmetatable
这个函数返回的是第一个参数的值
可以这样调用:1
2
3
4
5me = 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
11Student = 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
4local hello = loadfile("model_name.lua")
...
...
hello()
正常用法如下:mymod.lua
内容如下:1
2
3
4
5
6
7
8
9
10
11local xqdModel = {}
local function getname()
return "xqd"
end
function xqdModel.Greeting()
print("hello, my name is "..getname())
end
return xqdModel
然后就可以这样使用:1
2local xqd_model = require("mymod")
xqd_model.Greeting()