Lua语言入门(三)

来源:互联网 发布:tf卡数据恢复 编辑:程序博客网 时间:2024/06/05 22:47

协同程序

36、协同程序(coroutine)
4种状态:挂起(suspended)、运行(running)、死亡(dead)、正常(normal)

创建(挂起状态):

local co = coroutine.create( function()  print("coroutine") end)

启动或再次启动协程(状态由挂起改为运行):

coroutine.resume(co)

coroutine在创建的时候不会自动执行。

检查协程的状态:

coroutine.status(co)

协程在运行完之后,就处于死亡状态,再也无法返回。

使用yield:

local co =  coroutine.create( function()  for i=1,10 do   print(i)   coroutine.yield() --运行到这里让该协程挂起,之后通过调用coroutine.resume恢复它的运行  end end )coroutine.resume(co) --1coroutine.resume(co) --2coroutine.resume(co) --3coroutine.resume(co) --4coroutine.resume(co) --5

当一个协程 A 唤醒另一个协程 B ,协程 A 就处于一个特殊状态,称为“正常状态”。

local co =  coroutine.create( function(a, b)  print("the first resume params: ", a, b);  --在第一次调用resume,传递的额外参数都将视为协同程序主函数的参数;  print("resume params", coroutine.yield("yield return params")) --而yield返回值就是对应resume传入的参数  return "function return"  --当一个协同程序结束时,主函数返回值都将作为resume的返回值。 end )print(coroutine.resume(co, 1, 2))  --调用resume后返回的内容,第一个值为true则表示没有错误,后面所有值都是对应yield传入的值print(coroutine.resume(co, 3, 4, 5))--[[输出:the first resume params: 1 2true yield return paramsresume params 3 4 5true function return]]

36、协程应用于生产者消费者模式(最好把代码运行一下,再去理解)

function receive(prod) local status, value = coroutine.resume(prod) return valueendfunction send(x) coroutine.yield(x)endfunction producer() return coroutine.create(  function()   while true do    local x = io.read()    send(x)   end  end )endfunction filter(prod) return coroutine.create(  function()   for line = 1, math.huge do    local x = receive(prod)    x = string.format("%5d %s", line, x)    send(x)   end  end )endfunction consumer(prod) while true do  local x = receive(prod)  io.write(x, "\n") endendp = producer()f = filter(p)consumer(f)

37、非抢先式多线程(协程):当一个协程运行时,无法从外部停止,只有协程显示的挂起(yield),才会停止。

常用数据结构

38、数组:以数字作为key的table,在lua中习惯用 1 作为数组起始,长度可变

a = {}for i =1,10 do a[i] = 0endprint(#a) --计算数组长度--直接创建并初始化数组a = {7, 6, 5, 5, 7, 8, 9, 0, 0, 5, 3}

39、多维数组,可以用类似其它语言的方式表示多维,也可以利用一维数组表示。用稀疏矩阵表示一个图,table本身就是稀疏的,可以直接表示浪费内存。

mt = {}for i=1,10 do mt[i] = {} for j=1,10 do  mt[i][j] = 0 endend

遍历“稀疏矩阵”需要注意:一般使用pairs且只遍历那些非nil的元素。

pairs 和 ipairs 的区别:pairs 可以遍历表中所有的key,而ipairs 只能遍历到表中出现的一个不是整数的key

当然还有链表、队列、树、图等数据结构,这就不详细写了,这些东西和在其它语言里面是一样的

40、字符串连接:先把每个字符串存到一个数组里面,然后用table.concat连接,比用(..)连接更快更省

local a = {"A", "b", "C", "d", "E"} local s = table.concat(a)

数据持久化

41、数据文件(读取):lua常常被用来做数据存取,在lua中,所谓的数据文件就是按一定格式定义的lua文件,把该“数据文件”加载进内存,就可以直接用lua代码解析了。

local  count = 0function Entry(b) count = count + 1 print("load data call : "..b[1])end--dofile("data")--data文件中就写如下的代码,这里为了简便,就直接把数据写在这里了。Entry{--注意数据文件里面的Entry必须提前定义,其实数据文件里面的Entry在调用一个名叫Entry的函数 "A", "B", "C", "D", "E"}Entry{ "f", "g", "h", "i", "j"}print("number of entries : "..count)

42、数据持久化
保存无“环”形table:

function serialize(o) if type(o) == "number" then  io.write(0) elseif type(o) == "string" then  io.write(string.format("%q", o)) elseif type(o) == "table" then  io.write("{\n")  for k,v in pairs(o) do   io.write("  [")   serialize(k);   io.write("] = ")   serialize(v)   io.write(", \n")  end  io.write("}\n") else  --其它情况  error("can not serialize a"..type(o)) endendserialize({a = 'A', b = 'Q', c = '1'})

保存有“环”形table:

43、元表:就是普通一个table,可以设置为其他表的元表,元表中可定义实现一系列的元方法

t = {}t1 = {x = "a"}setmetatable(t, t1) --把 t1 设置为 t 的元表print(getmetatable(t)) --获得 t 的元表

44、元方法:定义于元表中的那些重载的方法

算术类元方法(__add(加法),__mul(乘法),__sub(减法),__div(除法),__unm(相反数),__mod(取模),__pow(幂)):

local t = {}t.__add = function(a, b) --定义加法的元方法 return a["value"] + b["value"]endlocal obj1 = {value = 1}setmetatable(obj1, t) --local obj2 = {value = 2}--setmetatable(obj1, t)print(obj1 + obj2) --加法的时候,会检查它们其中任意一个的元表,只要有名叫__add的元方法,就会调用它定义的加法运算

关系类元方法(__eq(等于)、__lt(小于)、__le(等于)):

字符串输出元方法(__tostring):local m = {}m.__tostring = function() return "meta function"endlocal a = {}setmetatable(a, m)print(a)

保护元表:使用用户既不能看也不能修改集合的元表,定义字段 __metatable

local m = {}m.__metatable = "not your business" --保护元表local a = {}setmetatable(a, m)print(getmetatable(a)) --not your businesssetmetatable(a, m) --cannot change protected metatable

table访问的元方法:
__index元方法:当访问一个table中不存在的字段时,解释器会去查找元表中名叫__index的元方法,如果没有该方法,返回nil,否则由这个元方法提供结果。

local m = {}m.__index = function() return "index nil"endlocal a = {}setmetatable(a, m)print(a[1]) --index nil

__newindex元方法:当对一个table中不存在的索引赋值时,解释器就会查找__newindex元方法,如果元表中有该元方法,就调用它而不执行赋值。

0 0
原创粉丝点击