linux:
lua官网
执行上图命令+make install
lua会安装到/usr/local下,你也可以修改Makefile中的INSTALL_TOP来修改安装的根路径,
注意将lua所在目录添加至PATH
lua安装内容包含如下:
测试:
交互式:
脚本:
注释
print("hi")
-- 单行注释
--[[
多行注释
]]--
标识符
标识符由字母、数字、下划线 组成,只能以下划线和字母开头,不要以下划线+大写字母组成标识符。
全局变量
没有赋值的变量为nil
print(a)
a=1
print(a)
a=nil
print(a)
没有任何有效值,就是一个nil。
nil由删除的变量,nil的类型为'nil'
-- 定义一个table,相当于map
myTab = {key1 = "value1", key2 = "value2"}
for k,v in pairs(myTab) do
print(k.."-"..v) end
print("删除key1")
myTab.key1 = nil
for k,v in pairs(myTab) do
print(k.."-"..v) end
print(x)
print(x == nil)
print(type(x) == "nil")
lua中只有false和nil 为false,其余都为true
if false or nil then
print("nil is true")
else
print("nil is false")
end
if 0 then
print("0 is true")
else
print("0 is false")
end
lua中,只有一种数字类型-number
8字节、双精度
print("测试number")
a=10
print(type(a))
用单引号或双引号
print('单引号字符串')
print("双引号字符串")
[[]]可以包含换行的字符串
i=[[
我是中国人
我是亚洲人
我是地球人
我是太阳系人
]]
print(i)
字符串与数字做数学运算时,优先将字符串转换成数字
print("测试字符串+")
print("1"+1)
print("1"+"1")
如果字符串不能转成数字将报错
print("测试字符串+")
print("1"+1)
print("1"+"1")
print("x"+1)
如果实现java中字符串连接,使用 .. 符号
print("测试字符串..")
print("1"..1)
print("1".."1")
print("x"..1)
计算字符串长度
print(#"aa")
table 可做数组和map
数组下标从1开始。
print("测试table")
tab1={}
tab2={"v1","v2","v3"}
tab3={key1="value1",key2="value2",key3="value3"}
print("-----打印tab3-----")
for k,v in pairs(tab3) do
print(k.."="..v)
end
print("-----打印tab2------")
for k,v in pairs(tab2) do
print(k.."="..v)
end
print("-----按数组索引打印数组------")
print(tab2[1])
print(tab2[2])
print(tab2[3])
print("-----nil相当于删除------")
tab3["key1"] = nil
for k,v in pairs(tab3) do
print(k.."="..v)
end
斐波拉系数列:
function fib(n)
if n == 1 or n == 2 then
return 1
else
return fib(n-1)+fib(n-2)
end
end
print("fib(10) = " ..fib(10))
匿名函数:
print("----测试匿名函数----")
function ff(tab,func)
for k,v in pairs(tab) do
print(func(k,v))
end
end
tab1={key1="v1",key2="v2"}
ff(tab1,
function(k,v)
return k.."="..v
end
)
thread:协程
userdata:存储c、c++数据类型。
变量
lua变量分为全局变量,局部变量
全局变量:默认,全局有效。
局部变量:从作用范围开始到作用范围结束。需加local 修饰。
a=1
function ff()
local b=1
end
print(a)
print(b)
变量的赋值
function ff2()
return 2,3
end
a=1
b=2
-- 交换
a,b = b,a
print(a,b)
-- 变量个数<值的个数,忽略多余的值
a,b,c = 1,2,3,4
print(a,b,c)
-- 变量个数>值的个数,不足nil
a,b,c,d = 1,2,3
print(a,b,c,d)
-- 多返回值的函数
a,b = ff2()
print(a,b)
索引
对table中的元素进行访问
tab = {k1="v1",k2="v2",k3="v3"}
print(tab["k1"])
print(tab.k1)
while(循环条件)
do
执行体;
对循环条件的控制;
end
a=1
while(a<=5)
do
print(a)
a=a+1
end
for
数值for
for var=expr1,expr2,expr3(var 从expr1到expr2,expr3 为步长,可为空,默认为1)
do
循环体
end
-- 打印10以内的奇数
for a=1,10,2
do
print(a)
end
泛型for
arr={"one","two","three"}
-- 只打印索引
for k in pairs(arr)
do
print(k)
end
-- 打印索引和值
for k,v in pairs(arr)
do
print(k,v)
end
repeat util
repeat
循环体
until(条件)
先执行循环体,直到满足条件;
a=1
repeat
print(a)
a=a+1
until(a>10)
if (成立) then
执行体1
else
执行体2
end
函数定义
范围:默认local
格式:
function 函数名(参数列表)
函数体;
return 返回值
end
-- 最大值函数:
function max(arg1,arg2)
local result = arg1
if (arg1 < arg2)then
result = arg2
end
return result
end
print(max(1,2))
多返回值函数
function findMax(arr)
local index=1;
local value=arr[index];
for k,v in pairs(arr)
do
if (v > value)then
index = k
value = v
end
end
return index,value
end
index,value = findMax({1,3,5,7,9})
print("最大值索引:"..index.."最大值:"..value)
可变参数
可变参数:arg = {...}
function sum(...)
local arg = {...}
local result=0;
for k,v in pairs(arg)
do
result = result + v
end
return result
end
print("和为:"..sum(1,2,3,4,5))
获取可变参数的个数: #arg
function Avg(...)
local arg = {...}
local result=0;
local count = #arg;
for k,v in pairs(arg)
do
result = result + v
end
return result/count
end
print("avg为:"..Avg(1,2,3,4,5,6))
函数参数列表中,存在固定参数和可变参数,固定参数全部写在前面
function fmtPrint(fmt,...)
io.write(string.format(fmt,...))
end
fmtPrint("%s\n","helloworld")
fmtPrint("%d+%d = %d\n",1,1,2)
选取可变参数的值:select
function ff4(...)
a,b,c = select(3,...)
return a,b,c
end
print(ff4(1,2,3,4,5,6,7,8,9))
算术运算符
+ 加 - 减 * 乘 / 除 % 取余 ^ 乘幂 - 负号 = 等号
关系运算符
== 等于
~= 不等于
>大于
>= 大于等于
<小于
<= 小于等于
逻辑运算符
与:and
或:or
非:not
一维数组:
选择排序:
function sort(arr,n)
for i=1,n-1,1
do
local k = i
for j=i+1,n,1
do
if (arr[j] < arr[k]) then
k = j
end
end
if (k ~= i) then
local tmp = arr[i]
arr[i] = arr[k]
arr[k] = tmp
end
end
return arr
end
arr = sort({4,3,2,1},4)
for i in pairs(arr)
do
print(arr[i].." ")
end
多维数组
function ff4()
arr={}
for i=1,3,1
do
arr[i]={}
for j=1,2,1
do
arr[i][j]=i*j
end
end
return arr
end
print("---------------------")
arr = ff4()
for i=1,3,1
do
for j=1,2,1
do
print(arr[i][j])
end
end
for 迭代器
pairs:会遍历所有key,value
ipairs:将跳过不是数字作为key的索引。
for 变量列表 in 迭代函数,状态常量,控制变量
do
循环体
end
1-9的平方:
print("-------迭代器的定义例子--------") -- 求平方 1-9的平方
function square(iteratorMaxCount,currentNumber)
if currentNumber < iteratorMaxCount then
currentNumber = currentNumber +1
-- if(currentNumber == 2) then
-- return nil,1
-- end
return currentNumber,currentNumber*currentNumber
end
end
for i,n in square,9,0
do
print(i,n)
end
table 可做数组、可做键值对
table 赋值时,新的table与旧的tabe共用一块内存。
tab={}
tab[1]="1"
print(tab[1])
tab = nil
print("-------------------")
tab={}
-- 类型为table
print(type(tab))
tab[1]="1号元素"
tab["a"]="a号元素"
print("tab a[1] = "..tab[1])
print("tab a[a] = "..tab["a"])
--赋值,newtab 与tab 共用一块内存。
newtab = tab
print("newtab a[1] = "..newtab[1])
print("newtab a[a] = "..newtab["a"])
-- newtab 发生修改,tab 也会修改
newtab["a"]="aa"
print("newtab a[a] = "..newtab["a"])
print("tab a[a] = "..tab["a"])
-- tab 为空,只是tab 变量为空,其指向的内存还由newtab指着,所以这块内存不会回收
tab=nil
print("newtab a[1] = "..newtab[1])
print("newtab a[a] = "..newtab["a"])
模块
模块中的局部成员不能被外部访问
module.lua
module={}
module.A ="module 中的A"
function module.func1()
print("module func1")
end
-- 局部函数
local function func2()
print("module func2")
end
function module.func3()
func2()
end
return module
调用:test.lua, module.lua
-- 相对路径
require("module")
print(module.A)
print(module.func1())
print(module.func3())
修改LUA_PATH=path/?.lua,可以让lua去其他地方寻找模块。
C包: 直接调用C库中的函数
print.c
#include
void print()
{
printf("hello world\n");
}
//gcc -o libprint.so -fPIC -shared print.c
或者C++编写的库
print.cc
#include
//外部接口处理成C格式
extern "C"
{
void print();
}
void print()
{
std::cout << "hello world\n";
}
//g++ -o libprint.so -fPIC -shared print.cc
test.lua
local path = "./libprint.so"
local f = package.loadlib(path, "print")
f()
允许我们改变 table 的行为,每个行为关联了对应的元方法
设置元表、获取元表
tab0 = {}
tab = setmetatable({}, tab0)
tab2 = getmetatable(tab)
-- tab0 与tab2 相同
print(tab0)
print(tab2)
__index 元方法
__index 包含table:在table未查找到键时,获取查找元表的__index键,如果找到且__index中包含一个table,则lua会在表格中查找相应的键。
tab1 = { key2 = "value2" }
tab2 = setmetatable({ key1 = "value1" }, { __index = tab1 })
print(tab2.key1)
print(tab2.key2)
__index 包含函数:在table未查找到键时,获取查找元表的__index键,如果找到且__index中包含一个函数,则lua会将键值传入函数。
mytable = setmetatable({ key1 = "value1" }, {
__index = function(mytable, key)
if key == "key2" then
return "metatablevalue"
else
return nil
end
end
})
print(mytable.key1, mytable.key2)
__index元方法总结:
1.在表中查找,如果找到,返回该元素,找不到则继续
2.判断该表是否有元表,如果没有元表,返回 nil,有元表则继续。
3.判断元表有没有 __index 方法,如果 __index 方法为 nil,则返回 nil;如果 __index 方法是一个表,则重复 1、2、3;如果 __index 方法是一个函数,则返回该函数的返回值。
__newindex 元方法
__newindex 包含table:如果对table进行赋值时,覆盖table中不存在键且table有元表,则查找__newindex元方法,如果找到且__newindex为一个table,则在这个table中赋值。
tab0 = {}
tab = setmetatable({ key1 = "value1" }, { __newindex = tab0 })
print(tab.key1)
-- print(tab0.key2)
tab.key1 = "v1"
tab.key2 = "v2"
print(tab.key1)
print(tab0.key2)
__newindex 包含方法:如果对table进行赋值时,覆盖table中不存在键且table有元表,则查找__newindex元方法,如果找到则调用这个方法。
mytable = setmetatable({ key1 = "value1" }, {
__newindex = function(mytable, key, value)
rawset(mytable, key, "\"" .. value .. "\"")
end
})
mytable.key1 = "new value"
mytable.key2 = 4
print(mytable.key1, mytable.key2)
为表添加操作符
实现两个数组相加:
function table_maxn(t)
local mn = 0
for k, v in pairs(t) do
if mn < k then
mn = k
end
end
return mn
end
mytable = setmetatable({ 1, 2, 3 }, {
__add = function(mytable, newtable)
for i = 1, table_maxn(newtable) do
table.insert(mytable, table_maxn(mytable) + 1, newtable[i])
end
return mytable
end
})
secondtable = { 4, 5, 6 }
mytable = mytable + secondtable
for k, v in ipairs(mytable) do
print(k, v)
end
其他可实现的表操作符:
__call元方法:将table自身变成一个方法。
两个table元素求和:
tab = setmetatable({ 1, 2, 3 }, {
__call = function(tab, newtable)
local sum = 0
for i in pairs(tab)
do
sum = sum + tab[i]
end
for i in pairs(newtable)
do
sum = sum + newtable[i]
end
return sum
end
})
newtable = { 4, 5, 6 }
print(tab(newtable))
__tostring 元方法:使得print不再是地址
返回table的元素和的字符串:
tab = setmetatable({ 1, 2, 3 }, {
__tostring = function(tab)
sum = 0
for i in pairs(tab)
do
sum = sum + tab[i]
end
return "table的和是: " .. sum
end
})
print(tab)
相关概念:
lua协程:拥有独立的堆栈、局部变量、pc,同时与其他协程共用全局变量和其他大部分东西。
lua协程与线程的区别:一个具有多线程的程序可以同时运行多个线程,而协同程序需要彼此协作运行,同一时刻只有一个协程运行,运行的协程只有被明确要求挂起时才会挂起。协同程序与同步的线程比较类似,多个线程等待同一个线程锁。
相关方法
coroutine.create():创建一个协程
coroutine.resume():重启一个协程
coroutine.yield():挂起一个协程
coroutine.status():返回协程的状态,死亡dead,暂停suspended,运行中running
coroutine.running():一个协程对应一个线程,返回running协程的线程号,以及是否为主线程。
死亡的协程不能再运行
co = coroutine.create(
function(i)
print(i)
end
)
coroutine.resume(co, 1) -- 1
print(coroutine.status(co)) --dead
print(coroutine.resume(co, 2)) -- false cannot resume dead coroutine
协程主动退出,暂停的协程可以继续运行
co = coroutine.create(
function()
for i = 1, 10, 1
do
print(i)
print(coroutine.status(co))
print(coroutine.running())
coroutine.yield()
end
end
)
coroutine.resume(co)
print(coroutine.status(co))
print("------------------")
coroutine.resume(co)
print(coroutine.status(co))
print("------------------")
coroutine.resume(co)
print(coroutine.status(co))
yield与resume的交互
co = coroutine.create(
function(a)
a = a + 1
print("第一次协同程序执行输出", a)
-- b将等于再次启动协程时,resume传入的参数
local b = coroutine.yield(a)
print("第二次协同程序执行输出", b)
return a
end
)
print(coroutine.resume(co, 1))
print(coroutine.resume(co, 20))
生产者与消费者(利用:lua协程天然的同步特点)
-- 生产者协程
function produce()
i = 0
while (true)
do
i = i + 1
coroutine.yield(i)
end
end
-- 消费者协程
function consume()
while (true)
do
local status, value = coroutine.resume(co1)
print(value)
-- sleep 1 s
os.execute("sleep 1")
end
end
co1 = coroutine.create(produce)
co2 = coroutine.create(consume)
-- 主协程等待
coroutine.resume(co2)
语法错误
运行错误
function add(a, b)
return a + b
end
print(add(1))
错误处理
assert(关系表达式,错误信息):assert首先检查第一个参数,若没问题,assert不做任何事情;否则,assert以第二个参数作为错误信息抛出。
function add(a, b)
assert(type(a) == "number", "a is not number")
assert(type(b) == "number", "a is not number")
return a + b
end
print(add(1))
error函数:终止正在执行的函数,并返回message的内容作为错误信息(error函数永远都不会返回)
function add(a, b)
if (type(a) ~= "number") then
error("a is not number")
end
if (type(b) ~= "number") then
error("b is not number")
end
return a + b
end
print(add(1, 1))
pcall:pcall接收一个函数和要传递给后者的参数,并执行,执行结果:有错误、无错误;返回值true或者或false, errorinfo。
function ff(i)
error("err")
print(i)
end
print(pcall(ff, 1))
xpcall:
xpcall接收第二个参数——一个错误处理函数,当错误发生时,Lua会在调用桟展开(unwind)前调用错误处理函数,于是就可以在这个函数中使用debug库来获取关于错误的额外信息了。
debug库提供了两个通用的错误处理函数:
debug.debug:提供一个Lua提示符,让用户来检查错误的原因
debug.traceback:根据调用桟来构建一个扩展的错误消息
xpcall(function(i)
print(i)
error('error..')
end, function() print(debug.traceback()) end, 33)
定义对象
student = {
name = "zhangsan",
age = "18",
gotoSchool = function(name)
print(name .. "去上学")
end
}
student.gotoSchool = function(name)
print(name .. "去上学")
end
function student.gotoSchool(name)
print(name .. "去上学")
end
student.gotoSchool(student.name)
构造函数
Student = { name = "default" }
function Student:new()
s = {}
setmetatable(s, { __index = self })
return s
end
s1 = Student:new()
s2 = Student:new()
print(s1.name)
print(s2.name)
s1.name = "zhangsan"
s2.name = "lisi"
print(s1.name)
print(s2.name)