昨天学习了协同程序,今天继续看看协同函数以及管道和过滤器。
既然说到了协同程序和线程有些类似,那一定记得学习线程时的“生产者和消费者”的问题了。不知道线程?没关系。所谓“生产者和消费者”是指一个函数不断地产生值,另一个函数不断地接收值。比如,一个函数从一个文件中读值,另一个函数则接收值写入文件中,下面就是这个例子。
那么send和receive函数是怎么交流的呢?记住,一个具有多个协同程序的程序在任意时刻只能运行一个协同程序。
利用昨天学习的协同程序,我们可以将生产函数写成协同程序,在send函数里挂起协同程序,然后receive函数里运行协同程序,而用消费函数去调用。
我们可以看到首先consumer()函数执行,在执行到调用receive()时,进入receive()函数启动了producer这个协同程序,于是,producer执行,当到了调用send()时,被挂起了,返回到了consumer函数中的receive处继续往下执行,并且一直循环。
这里就基本实现了我们的“生产和消费”的要求了。
如果,我们想要的不仅仅是读取什么值就写入什么值,而是想在这两个文件中转换一下呢?例如,我想将读取的值前面加个行号,表示这是原文件的第几行读取的。现在我们怎么来实现呢?
于是就有了一个叫做“过滤器(filter)”的东西,它的作用就是用来转换的。
依然是上面的例子。
既然说到了协同程序和线程有些类似,那一定记得学习线程时的“生产者和消费者”的问题了。不知道线程?没关系。所谓“生产者和消费者”是指一个函数不断地产生值,另一个函数不断地接收值。比如,一个函数从一个文件中读值,另一个函数则接收值写入文件中,下面就是这个例子。
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
那么send和receive函数是怎么交流的呢?记住,一个具有多个协同程序的程序在任意时刻只能运行一个协同程序。
利用昨天学习的协同程序,我们可以将生产函数写成协同程序,在send函数里挂起协同程序,然后receive函数里运行协同程序,而用消费函数去调用。
function send(x)
coroutine.yield(x)
end
producer = coroutine.create(function()
while true do
local x = io.read()
send(x)
end
end)
function receive()
local status , x = coroutine.resume(producer)
return x
end
function consumer()
while true do
local x = receive()
io.write(x,"\n")
end
end
consumer()
执行结果:
第一个“hello”是输入的,第二个“hello”是输出的。
我很想看看这些程序是怎么执行的,于是加入了一些调试语句,如下:function send(x)
coroutine.yield(x)
end
producer = coroutine.create(function()
print("1")
while true do
print("1.1")
local x = io.read()
send(x)
print("1.2")
end
end)
function receive()
local status , x = coroutine.resume(producer)
return x
end
function consumer()
print("2")
while true do
print("2.1")
local x = receive()
io.write(x,"\n")
print("2.2")
end
end
consumer()
执行结果:
我们可以看到首先consumer()函数执行,在执行到调用receive()时,进入receive()函数启动了producer这个协同程序,于是,producer执行,当到了调用send()时,被挂起了,返回到了consumer函数中的receive处继续往下执行,并且一直循环。
这里就基本实现了我们的“生产和消费”的要求了。
如果,我们想要的不仅仅是读取什么值就写入什么值,而是想在这两个文件中转换一下呢?例如,我想将读取的值前面加个行号,表示这是原文件的第几行读取的。现在我们怎么来实现呢?
于是就有了一个叫做“过滤器(filter)”的东西,它的作用就是用来转换的。
依然是上面的例子。
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 receive(prod)
local status , x = coroutine.resume(prod)
return x
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) -- string.format()函数第一个参数为格式,与c语言中相同
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)
这里的filter函数就是过滤器。这里的执行结果: