Lua点滴LuaLua脚本语言开发

Lua语言入门(三)

2016-09-24  本文已影响98人  小飞不会飞_

协同程序

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) --1
coroutine.resume(co) --2
coroutine.resume(co) --3
coroutine.resume(co) --4
coroutine.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 2
true yield return params

resume params 3 4 5
true function return
]]

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

function receive(prod)
 local status, value = coroutine.resume(prod)
 return value
end

function send(x)
 coroutine.yield(x)
end

function producer()
 return coroutine.create(
  function()
   while true do
    local x = io.read()
    send(x)
   end
  end
 )
end

function 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
 )
end

function consumer(prod)
 while true do
  local x = receive(prod)
  io.write(x, "\n")
 end
end

p = producer()
f = filter(p)
consumer(f)

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

常用数据结构

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

a = {}
for i =1,10 do
 a[i] = 0
end
print(#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
 end
end

遍历“稀疏矩阵”需要注意:一般使用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 = 0
function 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))
 end
end

serialize({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"]
end

local 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"
end

local a = {}
setmetatable(a, m)

print(a)

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

local m = {}
m.__metatable = "not your business" --保护元表

local a = {}
setmetatable(a, m)

print(getmetatable(a)) --not your business
setmetatable(a, m) --cannot change protected metatable

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

local m = {}
m.__index = function()
 return "index nil"
end

local a = {}
setmetatable(a, m)

print(a[1]) --index nil

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

上一篇 下一篇

猜你喜欢

热点阅读