Lua 學習筆記(七) —— 協同程序(二)

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


關於執行順序,可以讓其輸出一些調試語句,進行查看。
發佈了49 篇原創文章 · 獲贊 30 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章