既然說到了協同程序和線程有些類似,那一定記得學習線程時的“生產者和消費者”的問題了。不知道線程?沒關係。所謂“生產者和消費者”是指一個函數不斷地產生值,另一個函數不斷地接收值。比如,一個函數從一個文件中讀值,另一個函數則接收值寫入文件中,下面就是這個例子。
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函數就是過濾器。這裏的執行結果: