Ruby Fiber指南(三)过滤器
生活随笔
收集整理的這篇文章主要介紹了
Ruby Fiber指南(三)过滤器
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Ruby Fiber指南(一)基礎(chǔ)
??? Ruby Fiber指南(二)參數(shù)傳遞
??? Ruby Fiber指南(三)過濾器
???Ruby Fiber指南(四)迭代器
??? Ruby Actor指南(五)實現(xiàn)Actor
? ?? 在學(xué)習(xí)了Fiber的基礎(chǔ)知識之后,可以嘗試用Fiber去做一些比較有趣的事情。這一節(jié)將講述如何使用Fiber來實現(xiàn)類似unix系統(tǒng)中的管道功能。在unix系統(tǒng)中,可以通過管道將多個命令組合起來做一些強大的功能,最常用的例如查找所有的java進程:
ps?aux|grep?java 通過組合ps和grep命令來實現(xiàn),ps的輸出作為grep的輸入,如果有更多的命令就形成了一條過濾鏈。過濾器本質(zhì)上還是生產(chǎn)者和消費者模型,前一個過濾器產(chǎn)生結(jié)果,后一個過濾器消費這個結(jié)果并產(chǎn)生新的結(jié)果給下一個過濾器消費。因此我們就從最簡單的生產(chǎn)者消費者模型實現(xiàn)說起。
我們要展示的這個例子場景是這樣:生產(chǎn)者從標(biāo)準(zhǔn)輸入讀入用戶輸入并發(fā)送給消費者,消費者打印這個輸入,整個程序是由消費者驅(qū)動的,消費者喚醒生存者去讀用戶輸入,生產(chǎn)者讀到輸入后讓出執(zhí)行權(quán)給消費者去打印,整個過程通過生產(chǎn)者和消費者的協(xié)作完成。
生產(chǎn)者發(fā)送是通過yield返回用戶輸入給消費者(還記的上一節(jié)嗎?):
def?send(x)
??Fiber.yield(x)
end
而消費者的接收則是通過喚醒生產(chǎn)者去生產(chǎn):
def?receive(prod)
??prod.resume
end
生產(chǎn)者是一個Fiber,它的任務(wù)就是等待用戶輸入并發(fā)送結(jié)果給消費者:
def?producer()
??Fiber.new?do
????while?true
??????x=readline.chomp
??????send(x)
????end
??end
end
消費者負(fù)責(zé)驅(qū)動生產(chǎn)者,并且在接收到結(jié)果的時候打印,消費者是root fiber:
def?consumer(producer)
??while?true
????x=receive(producer)
????break?if?x=='quit'
????puts?x
??end
end
??? 最終的調(diào)用如下:
consumer(producer()) ?? 完整的程序如下:
#生產(chǎn)者消費者
require?'fiber'
def?send(x)
??Fiber.yield(x)
end
def?receive(prod)
??prod.resume
end
def?producer()
??Fiber.new?do
????while?true
??????x=readline.chomp
??????send(x)
????end
??end
end
def?consumer(producer)
??while?true
????x=receive(producer)
????break?if?x=='quit'
????puts?x
??end
end
if?$0==__FILE__
??consumer(producer())
end
?? 讀者可以嘗試在ruby1.9下運行這個程序,每次程序都由消費者驅(qū)動生產(chǎn)者去等待用戶輸入,用戶輸入任何東西之后回車,生產(chǎn)者開始運行并將讀到的結(jié)果發(fā)送給消費者并讓出執(zhí)行權(quán)(通過yield),消費者在接收到y(tǒng)ield返回的結(jié)果后打印這個結(jié)果,因此整個交互過程是一個echo的例子。
最終的調(diào)用consumer(producer())已經(jīng)有過濾器的影子在了,如果我們希望在producer和consumer之間插入其他過程對用戶的輸入做處理,也就是安插過濾器,那么新的過濾器也將作為fiber存在,新的fiber消費producer的輸出,并輸出新的結(jié)果給消費者,例如我們希望將用戶的輸入結(jié)果加上行號再打印,那么就插入一個稱為filter的fiber:
def?filter(prod)
??return?Fiber.new?do
????line=1
????while?true
??????value=receive(prod)
??????value=sprintf("%5d?%s",line,value)
??????send(value)
??????line=line.succ
????end
??end
end
??? 最終組合的調(diào)用如下:
?consumer(filter(producer())) ?? 類似unix系統(tǒng)那樣,簡單的加入新的fiber組合起來就可以為打印結(jié)果添加行號。
類似consumer(filter(producer()))的調(diào)用方式盡管已經(jīng)很直觀,但是我們還是希望能像unix系統(tǒng)那樣調(diào)用,也就是通過豎線作為管道操作符:
producer?|?filter?|?consumer 這樣的調(diào)用方式更將透明直觀,清楚地表明整個過濾器鏈的運行過程。幸運的是在Ruby中支持對|方法符的重載,因此要實現(xiàn)這樣的操作符并非難事,只要對Fiber做一層封裝即可,下面給出的代碼來自《Programming ruby》的作者Dave Thomas的blog:
class?PipelineElement
???attr_accessor?:source
???def?initialize
??????@fiber_delegate?=?Fiber.new?do
?????????process
??????end
???end
???def?|(other)
??????other.source?=?self
??????other
???end
???def?resume
??????@fiber_delegate.resume
???end
???def?process
??????while?value?=?input
?????????handle_value(value)
??????end
???end
???def?handle_value(value)
??????output(value)
???end
???def?input
??????@source.resume
???end
???def?output(value)
??????Fiber.yield(value)
???end
end
這段代碼非常巧妙,將Fiber和Ruby的功能展示的淋漓盡致。大致解說下,PipelineElement作為任何一個過濾器的父類,其中封裝了一個fiber,這個fiber默認(rèn)執(zhí)行process,在process方法中可以看到上面生產(chǎn)者和消費者例子的影子,input類似receive方法調(diào)用前置過濾器(source),output則將本過濾器處理的結(jié)果作為參數(shù)傳遞給yield并讓出執(zhí)行權(quán),讓這個過濾器的調(diào)用者(也就是后續(xù)過濾器)得到結(jié)果并繼續(xù)處理。PipelineElement實現(xiàn)了“|”方法,用于組合過濾器,將下一個過濾器的前置過濾器設(shè)置為本過濾器,并返回下一個過濾器。整個過濾鏈的驅(qū)動者是最后一個過濾器。
有了這個封裝,那么上面生產(chǎn)者消費者的例子可以改寫為:
class?Producer?<?PipelineElement
???def?process
?????while?true
???????value=readline.chomp
???????handle_value(value)
?????end
???end
end
class?Filter?<?PipelineElement
??def?initialize
????@line=1
????super()
??end
??def?handle_value(value)
????value=sprintf("%5d?%s",@line,value)
????output(value)
????@line=@line.succ
??end
end
class?Consumer?<?PipelineElement
??def?handle_value(value)
????puts?value
??end
end
?? 現(xiàn)在的調(diào)用方式可以跟unix的管道很像了:
producer=Producer.new
filter=Filter.new
consumer=Consumer.new
pipeline?=?producer?|?filter?|?consumer
pipeline.resume 如果你打印pipeline對象,你將看到一條清晰的過濾鏈,
#<Consumer:0x8f08bf4?@fiber_delegate=#<Fiber:0x8f08a88>,?@source=#<Filter:0x8f08db4?@line=1,?@fiber_delegate=#<Fiber:0x8f08d60>,?@source=#<Producer:0x8f09054?@fiber_delegate=#<Fiber:0x8f09038>>>> 文章轉(zhuǎn)自莊周夢蝶? ,原文發(fā)布時間2010-03-11
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
??? Ruby Fiber指南(二)參數(shù)傳遞
??? Ruby Fiber指南(三)過濾器
???Ruby Fiber指南(四)迭代器
??? Ruby Actor指南(五)實現(xiàn)Actor
? ?? 在學(xué)習(xí)了Fiber的基礎(chǔ)知識之后,可以嘗試用Fiber去做一些比較有趣的事情。這一節(jié)將講述如何使用Fiber來實現(xiàn)類似unix系統(tǒng)中的管道功能。在unix系統(tǒng)中,可以通過管道將多個命令組合起來做一些強大的功能,最常用的例如查找所有的java進程:
ps?aux|grep?java 通過組合ps和grep命令來實現(xiàn),ps的輸出作為grep的輸入,如果有更多的命令就形成了一條過濾鏈。過濾器本質(zhì)上還是生產(chǎn)者和消費者模型,前一個過濾器產(chǎn)生結(jié)果,后一個過濾器消費這個結(jié)果并產(chǎn)生新的結(jié)果給下一個過濾器消費。因此我們就從最簡單的生產(chǎn)者消費者模型實現(xiàn)說起。
我們要展示的這個例子場景是這樣:生產(chǎn)者從標(biāo)準(zhǔn)輸入讀入用戶輸入并發(fā)送給消費者,消費者打印這個輸入,整個程序是由消費者驅(qū)動的,消費者喚醒生存者去讀用戶輸入,生產(chǎn)者讀到輸入后讓出執(zhí)行權(quán)給消費者去打印,整個過程通過生產(chǎn)者和消費者的協(xié)作完成。
生產(chǎn)者發(fā)送是通過yield返回用戶輸入給消費者(還記的上一節(jié)嗎?):
def?send(x)
??Fiber.yield(x)
end
而消費者的接收則是通過喚醒生產(chǎn)者去生產(chǎn):
def?receive(prod)
??prod.resume
end
生產(chǎn)者是一個Fiber,它的任務(wù)就是等待用戶輸入并發(fā)送結(jié)果給消費者:
def?producer()
??Fiber.new?do
????while?true
??????x=readline.chomp
??????send(x)
????end
??end
end
消費者負(fù)責(zé)驅(qū)動生產(chǎn)者,并且在接收到結(jié)果的時候打印,消費者是root fiber:
def?consumer(producer)
??while?true
????x=receive(producer)
????break?if?x=='quit'
????puts?x
??end
end
??? 最終的調(diào)用如下:
consumer(producer()) ?? 完整的程序如下:
#生產(chǎn)者消費者
require?'fiber'
def?send(x)
??Fiber.yield(x)
end
def?receive(prod)
??prod.resume
end
def?producer()
??Fiber.new?do
????while?true
??????x=readline.chomp
??????send(x)
????end
??end
end
def?consumer(producer)
??while?true
????x=receive(producer)
????break?if?x=='quit'
????puts?x
??end
end
if?$0==__FILE__
??consumer(producer())
end
?? 讀者可以嘗試在ruby1.9下運行這個程序,每次程序都由消費者驅(qū)動生產(chǎn)者去等待用戶輸入,用戶輸入任何東西之后回車,生產(chǎn)者開始運行并將讀到的結(jié)果發(fā)送給消費者并讓出執(zhí)行權(quán)(通過yield),消費者在接收到y(tǒng)ield返回的結(jié)果后打印這個結(jié)果,因此整個交互過程是一個echo的例子。
最終的調(diào)用consumer(producer())已經(jīng)有過濾器的影子在了,如果我們希望在producer和consumer之間插入其他過程對用戶的輸入做處理,也就是安插過濾器,那么新的過濾器也將作為fiber存在,新的fiber消費producer的輸出,并輸出新的結(jié)果給消費者,例如我們希望將用戶的輸入結(jié)果加上行號再打印,那么就插入一個稱為filter的fiber:
def?filter(prod)
??return?Fiber.new?do
????line=1
????while?true
??????value=receive(prod)
??????value=sprintf("%5d?%s",line,value)
??????send(value)
??????line=line.succ
????end
??end
end
??? 最終組合的調(diào)用如下:
?consumer(filter(producer())) ?? 類似unix系統(tǒng)那樣,簡單的加入新的fiber組合起來就可以為打印結(jié)果添加行號。
類似consumer(filter(producer()))的調(diào)用方式盡管已經(jīng)很直觀,但是我們還是希望能像unix系統(tǒng)那樣調(diào)用,也就是通過豎線作為管道操作符:
producer?|?filter?|?consumer 這樣的調(diào)用方式更將透明直觀,清楚地表明整個過濾器鏈的運行過程。幸運的是在Ruby中支持對|方法符的重載,因此要實現(xiàn)這樣的操作符并非難事,只要對Fiber做一層封裝即可,下面給出的代碼來自《Programming ruby》的作者Dave Thomas的blog:
class?PipelineElement
???attr_accessor?:source
???def?initialize
??????@fiber_delegate?=?Fiber.new?do
?????????process
??????end
???end
???def?|(other)
??????other.source?=?self
??????other
???end
???def?resume
??????@fiber_delegate.resume
???end
???def?process
??????while?value?=?input
?????????handle_value(value)
??????end
???end
???def?handle_value(value)
??????output(value)
???end
???def?input
??????@source.resume
???end
???def?output(value)
??????Fiber.yield(value)
???end
end
這段代碼非常巧妙,將Fiber和Ruby的功能展示的淋漓盡致。大致解說下,PipelineElement作為任何一個過濾器的父類,其中封裝了一個fiber,這個fiber默認(rèn)執(zhí)行process,在process方法中可以看到上面生產(chǎn)者和消費者例子的影子,input類似receive方法調(diào)用前置過濾器(source),output則將本過濾器處理的結(jié)果作為參數(shù)傳遞給yield并讓出執(zhí)行權(quán),讓這個過濾器的調(diào)用者(也就是后續(xù)過濾器)得到結(jié)果并繼續(xù)處理。PipelineElement實現(xiàn)了“|”方法,用于組合過濾器,將下一個過濾器的前置過濾器設(shè)置為本過濾器,并返回下一個過濾器。整個過濾鏈的驅(qū)動者是最后一個過濾器。
有了這個封裝,那么上面生產(chǎn)者消費者的例子可以改寫為:
class?Producer?<?PipelineElement
???def?process
?????while?true
???????value=readline.chomp
???????handle_value(value)
?????end
???end
end
class?Filter?<?PipelineElement
??def?initialize
????@line=1
????super()
??end
??def?handle_value(value)
????value=sprintf("%5d?%s",@line,value)
????output(value)
????@line=@line.succ
??end
end
class?Consumer?<?PipelineElement
??def?handle_value(value)
????puts?value
??end
end
?? 現(xiàn)在的調(diào)用方式可以跟unix的管道很像了:
producer=Producer.new
filter=Filter.new
consumer=Consumer.new
pipeline?=?producer?|?filter?|?consumer
pipeline.resume 如果你打印pipeline對象,你將看到一條清晰的過濾鏈,
#<Consumer:0x8f08bf4?@fiber_delegate=#<Fiber:0x8f08a88>,?@source=#<Filter:0x8f08db4?@line=1,?@fiber_delegate=#<Fiber:0x8f08d60>,?@source=#<Producer:0x8f09054?@fiber_delegate=#<Fiber:0x8f09038>>>> 文章轉(zhuǎn)自莊周夢蝶? ,原文發(fā)布時間2010-03-11
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結(jié)
以上是生活随笔為你收集整理的Ruby Fiber指南(三)过滤器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: poj2104(划分树模板)
- 下一篇: 小白杨入住云栖社区