书本下载地址 http://download.csdn.net/detail/myy2012/5349646
本部分下载地址 http://download.csdn.net/detail/myy2012/5353143
lua程序设计第二版 读书笔记(1-4章)
第一章 开始
第二章 类型与值
第三章 表达式
第四章 语句
http://blog.csdn.net/myy2012/article/details/8900424
lua程序设计第二版 读书笔记(5-8章)
第五章 函数
第六章 深入函数
第七章 迭代器与泛型for
第八章 编译执行与错误
http://blog.csdn.net/myy2012/article/details/8906466
lua程序设计第二版 读书笔记(9-10章)
第九章 协同程序
第十章 完整的实例
http://blog.csdn.net/myy2012/article/details/8911206
lua程序设计第二版 读书笔记(11-14章)
第十一章 数据结构
第十二章 数据文件与持久性
第十三章 元表metatable与元方法meatmethod
第十四章 环境
http://blog.csdn.net/myy2012/article/details/8914457
lua程序设计第二版 读书笔记(15-17章)
第十五章 模块与包
第十六章 面向对象编程
第十七章 弱引用 table
http://blog.csdn.net/myy2012/article/details/8921632
lua程序设计第二版 读书笔记(18-21章)
第十八章 数学库
第十九章 table库
第二十章 字符串库
第二十一章 IO库
http://blog.csdn.net/myy2012/article/details/8925895
lua程序设计第二版 读书笔记(22-23章)
第二十二章 操作系统库
第二十三章 调试库
http://blog.csdn.net/myy2012/article/details/8930181
协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈、局部变量和指令指针,同时又与其他协同程序共享全局变量和其他大部分东西。
一个具有多个协同程序的程序在任意时刻只能运行一个协同程序,并正在运行的协同程序只会在其显式地要求挂起(suspend)时,它的执行才会暂停。
9.1协同程序基础
Lua将所有有关于协同程序的函数放置在一个名为“coroutine”的table中。函数create用于创建新的协同程序,它只有一个参数(一个函数)。该函数的代码就是协同程序所需执行的内容。Create会返回一个thread类型的值,用以表示新的协同程序。例如:
co=coroutine.create(function() print("hi") end)
print(co) --thread: 005EB9B8
一个协同程序可以处于4种不同的状态:挂起(suspended)、运行(running)、死亡(dead)和正常(normal)。当创建一个协同程序时,它处于挂起状态(协同程序不会在创建它时自动执行其内容)。可以通过函数status来检查协同程序的状态:
print( coroutine.status( co )) -- suspended
coroutine.resume用于启动或者再次启动一个协同程序的执行,并将状态从挂起改为运行。
coroutine.resume(co) -- hi
正常状态:当一个协同程序A唤醒另一个协同程序B时,A就处于一个特殊状态(正常状态normal),既不是挂起状态(无法继续A的执行),也不是运行状态(B在运行)。
Lua的协同程序可以通过一对resume-yield来交换数据。
A. 在第一次调用resume时,并没有对应的yield在等待它,因此所有传递给resume的额外参数都将视为协同程序主函数的参数。例如:
co3=coroutine.create(function(a, b, c)
print("co3", a, b, c)
end)
coroutine.resume(co3, 1, 2) --co3 1 2 nil
B. 在resume调用返回的内容中,第一个值为true 表示没有错误,而后面所有的值都是对应yield传入的参数。例如:
co4=coroutine.create(function(a, b)
coroutine.yield(a+b, a-b)
end)
print("co4", coroutine.resume(co4, 25, 10)) --co4 true 35 15
C. yield返回的额外值就是对应resume传入的参数。例如:
co5=coroutine.create(function()
print("co5", coroutine.yield())
end)
coroutine.resume(co5)
coroutine.resume(co5, 4, 5) --co5 4 5
D. 当一个协同程序结束时,它的主函数所返回的值都将作为对应的resume的返回值。例如:
co6=coroutine.create(function()
return 6, 7
end)
print("co6",coroutine.resume(co6))
非对称的协同程序(asymmetric coroutine):Lua提供了2个函数来控制协同程序的执行,一个用于挂起执行,另一个用于恢复执行。有人称之为“semi-coroutine”。
9.2协同程序与过滤器
一个关于协同程序的经典示例就是“生产者-消费者”的问题。
function producer()
while true do
local x=io.read() --产生新的值
send(x) --发送给消费者
end
end
function consumer()
while true do
local x=receive() --从生产者接收值
io.write(x, “\n”) --消费新的值
end
end
协同程序被称为是一种匹配生产者和消费者的理想工具,一对resume-yield完全一改典型的调用者与被调用者之间的关系。当一个协同程序调用yield时,它不是进入一个新的函数,而是从一个悬而未决的resume调用中返回;同样对于resume的调用也不会启动一个新函数,而是从一次yield调用中返回。
消费者驱动(consumer-driven)模式:当消费者需要一个新值时,它唤醒生产者。
function receive()
local statue, value = coroutine.resume(producer)
return value
end
function send(x)
coroutine.yield(x)
end
过滤器(filter):是一种位于生产者和消费者之间的处理功能,可用于对数据的一些交换。
function filter(pro)
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
)
9.3以协同程序实现迭代器
功能:遍历某个数组的所有排列组合的形式。
function permgen(a, n)
n=n or #a
if n<=1 then
coroutine.yield(a) --
else
for i=1, n do
a[n], a[i]=a[i], a[n] --将第i个元素放到数组末尾
permgen(a, n-1) --递归调用
a[n], a[i]=a[i], a[n] --恢复第i个元素
end
end
end
定义一个工厂函数permutations,用于将生成函数放到一个协同程序中运行,并出具迭代器函数(只是简单地唤醒协同程序)。函数permutations是将一条唤醒协同程序的调用包装在一个函数中。
function permutations(a)
local co=coroutine.create(function() permgen(a) end)
return function() --迭代器
local code, res=coroutine.resume(co) --开启
return res --返回的res就是传入到函数permgen中的参数a
end
end
function printResult(a)
for i=1, #a do
io.write(a[i], " ")
end
io.write("\n")
end
for p in permutations({1, 3, 5}) do
printResult(p) --调用打印函数
end
9.4 非抢先式的(non-preemptive)多线程
协同程序提供了一种协作式的多线程,每个协同程序都等于一个线程。一对yield-resume可以将执行权在不同线程之间切换。有一点不同的就是:协同程序运行时是无法从外部停止它的,只有当协同程序显式地要求挂起时(调用yield),它才会停止。
对于非抢占式的多线程来说,只要一个线程调用一个阻塞(blocking)操作,整个程序在该操作完成前都会停止下来。但是这种行为对于大多数应用程序来说的无法接受的。
require "socket"
host="www.w3.org"
file="/TR/REC-html32.html"
--------------------------------------------------------------
function receive(connection)
connection:settimeout(0)
local s, status, partial=connection:receive(2^10)
if status=="timeout" then
--coroutine.yield(connection)
end
return s or partial, status
end
函数的实现:
function download(host, file)
打开一个TCP连接,连接到该站点的80端口
local c=assert(socket.connect(host, 80))
local count=0
返回一个连接对象,可以用它来发送文件请求
c:send("GET "..file.." HTTP/1.0\r\n\r\n")
while true do
local s, status, partial=receive(c)
count=count+#(s or partial)
if status=="closed" then
break
end
end
c:close()
print(file, count)
end
download(host, file)
10.1 数据描述
将Lua作为一种数据描述语言。
要读取这些数据,程序只需简单地给出一个关于entry的合适定义,然后将数据文件作为一个程序来运行(通过dofile)。注意,必须对所有的条目遍历两次,第一次为获得标题列表,第二次为获得项目描述。
entry的定义如下:
entry={
title="Tecgraf",
org="Computer Graphics ",
url="http://www.tecgraf.com",
contact="waldemar ...",
description=[[
Tecgraf is the result of ...
]]
}
函数fwrite的实现:
function fwrite(fmt, ...)
return io.write(string.format(fmt, ...))
end
function writeheader()
io.write([[
Projects using Lua
Here are brief descriptions of Some Projects around
the world that use Lua.
]])
end
函数entry1的实现:
function entry1(o)
count=count+1
local title=o.title or '(no title)'
fwrite('%s', count, title)
end
函数entry2的实现:
function entry2(o)
count=count+1
fwrite('
\n\n')
local href=o.url and string.format(' href="%s", o.url') or ''
local title=o.title or o.org or 'org'
fwrite('\n', count, href, title)
if o.title and o.org then
fwrite('
\n%s', o.org)
end
fwrite('<\n
>\n')
if o.description then
fwrite('%s\n', string.gsub(o.description), '\n\n+', '
\n')
end
end
函数writetail的实现
function writetail()
fwrite('\n')
end
------------------------------------
测试代码如下:
local inputfile='db.lua'
f=loadfile(inputfile)
writeheader()
count=0
entry=entry1
fwrite('\n')
f()
fwrite('
\n')
count=0
entry=entry2
f()
writetail()
10.2 马尔可夫链(markov chain)算法
略
第一部分完