<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢(mèng)蝶

    生活、程序、未來(lái)
       :: 首頁(yè) ::  ::  :: 聚合  :: 管理

        Ruby Fiber指南(一)基礎(chǔ)
        Ruby Fiber指南(二)參數(shù)傳遞
        Ruby Fiber指南(三)過(guò)濾器
        Ruby Fiber指南(四)迭代器
        Ruby Actor指南(五)實(shí)現(xiàn)Actor

         上一節(jié)介紹了利用Fiber實(shí)現(xiàn)類unix管道風(fēng)格的過(guò)濾鏈,這一節(jié)將介紹利用Fiber來(lái)實(shí)現(xiàn)迭代器,我們可以將循環(huán)的迭代器看作生產(chǎn)者-消費(fèi)者模式的特殊的例子。迭代函數(shù)產(chǎn)生值給循環(huán)體消費(fèi)。所以可以使用Fiber來(lái)實(shí)現(xiàn)迭代器。協(xié)程的一個(gè)關(guān)鍵特征是它可以不斷顛倒調(diào)用者與被調(diào)用者之間的關(guān)系,這樣我們毫無(wú)顧慮的使用它實(shí)現(xiàn)一個(gè)迭代器,而不用保存迭代函數(shù)返回的狀態(tài),也就是說(shuō)無(wú)需在迭代函數(shù)中保存狀態(tài),狀態(tài)的保存和恢復(fù)交由Fiber自動(dòng)管理。

         這一節(jié)的介紹以一個(gè)例子貫穿前后,我們將不斷演化這個(gè)例子,直到得到一個(gè)比較優(yōu)雅的可重用的代碼,這個(gè)例子就是求數(shù)組的全排列。如數(shù)組[1,2,3]的全排列包括6種排列:
    2 3 1
    3 2 1
    3 1 2
    1 3 2
    2 1 3
    1 2 3
    全排列的遞歸算法實(shí)現(xiàn)很簡(jiǎn)單,我們用Ruby實(shí)現(xiàn)如下:

    #全排列的遞歸實(shí)現(xiàn)
    def permgen (a, n)
        
    if n == 0 then
           printResult(a)
        
    else
            n.times do 
    |i|
               a[n
    -1], a[i] = a[i], a[n-1]
               permgen(a, n 
    - 1)
               a[n
    -1], a[i] = a[i], a[n-1]
           end
        end
    end

    def printResult (a)
        puts a.join(
    " ")
    end

    permgen([
    1,2,3,4],4)
    算法的思路是這樣:
    將數(shù)組中的每一個(gè)元素放到最后,依次遞歸生成所有剩余元素的排列,沒(méi)完成一個(gè)排列就打印出來(lái)。很顯然,這里有消費(fèi)者和生產(chǎn)者的關(guān)系存在,生產(chǎn)者負(fù)責(zé)產(chǎn)生排列,消費(fèi)者負(fù)責(zé)打印任務(wù),整個(gè)程序由消費(fèi)者驅(qū)動(dòng),因此用Fiber改寫如下:

    第一步,將打印任務(wù)修改為Fiber#yield,生產(chǎn)者產(chǎn)生一個(gè)排列后將結(jié)果傳遞給消費(fèi)者并讓出執(zhí)行權(quán):
    def permgen (a, n)
        
    if n == 0 then
           Fiber.
    yield(a)
        ……
    end

    第二步,實(shí)現(xiàn)一個(gè)迭代器工廠,返回一個(gè)匿名的迭代函數(shù),迭代函數(shù)請(qǐng)求Fiber產(chǎn)生一個(gè)新的排列:
    def perm(a)
      f
    =Fiber.new do
            permgen(a,a.size)
        end
      
    return lambda{ f.resume if f.alive? }
    end

    這樣一來(lái)我們就可以利用一個(gè)while循環(huán)來(lái)打印全排列:
    it=perm([1,2,3,4])

    while a=it.call
       printResult(a)
    end

        注意到,在perm方法中有一個(gè)很常見(jiàn)的模式,就是將對(duì)Fiber的resume封裝在一個(gè)匿名函數(shù)內(nèi),在lua為了支持這種模式還特意提供了一個(gè)coroutine.wrap方法來(lái)方便編程,在Ruby Fiber中卻沒(méi)有,不過(guò)我們可以自己實(shí)現(xiàn)下,利用open-class的特性實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單:
    #為Fiber添加wrap方法
    class Fiber
      
    def self.wrap
        
    if block_given?
          f
    =Fiber.new do |*args|
             
    yield *args
          end
          
    return lambda{|*args| f.resume(*args) if f.alive? }
        end
      end
    end
     
        Fiber#wrap方法跟new方法一樣,創(chuàng)建一個(gè)新的Fiber,但是返回的是一個(gè)匿名函數(shù),這個(gè)匿名函數(shù)負(fù)責(zé)去調(diào)用fiber的resume,利用wrap改寫perm方法變得更簡(jiǎn)潔:
    def perm(a)
      Fiber.wrap{ permgen(a,a.size) }
    end

        但是還不夠,while循環(huán)的方式還是不夠優(yōu)雅,每次都需要明確地調(diào)用迭代器的call方法,這一點(diǎn)讓人挺不舒坦,如果能像for...in那樣的泛型循環(huán)就好了,我們知道Ruby中的for...in其實(shí)是一個(gè)語(yǔ)法糖衣,都是轉(zhuǎn)變成調(diào)用集合的each方法并傳入處理的block,因此,要想實(shí)現(xiàn)一個(gè)優(yōu)雅的迭代器,我們做下封裝就好了:

    class FiberIterator
      
    def initialize
        @fiber_wrap
    =Fiber.wrap do
            
    yield
        end
      end
      
    def each
        
    while value=@fiber_wrap.call
          
    yield value
        end
      end
    end

    那么現(xiàn)在的perm方法變成了創(chuàng)建一個(gè)迭代器FiberIterator:
    def perm(a)
      FiberIterator.new{ permgen(a,a.size) }
    end
    這樣一來(lái)我們就可以通過(guò)for...in來(lái)調(diào)用迭代器了

    it=perm([1,2,3,4])
    for a in it
      printResult(a)
    end


       

        
    主站蜘蛛池模板: 手机在线免费视频| 久久国产精品亚洲综合| 一级毛片视频免费| 久久精品国产亚洲AV麻豆不卡 | 亚洲欧美日韩中文二区| 亚洲?V无码成人精品区日韩| 成人无码精品1区2区3区免费看| 亚洲男女一区二区三区| 免费大学生国产在线观看p| 国产午夜无码精品免费看动漫| 日本亚洲精品色婷婷在线影院| 亚洲成av人片一区二区三区| 99精品一区二区免费视频| 亚洲avav天堂av在线网毛片| 香蕉蕉亚亚洲aav综合| 最近最好的中文字幕2019免费 | 国产免费一级高清淫曰本片 | 亚洲综合久久精品无码色欲| 最新精品亚洲成a人在线观看| 亚洲精品动漫免费二区| 伊人免费在线观看| 国产亚洲精品2021自在线| 亚洲理论片在线观看| 国产偷国产偷亚洲高清日韩 | 激情内射亚洲一区二区三区| 国产高清在线精品免费软件| 69免费视频大片| 成人片黄网站色大片免费观看cn| 亚洲AV综合色区无码二区偷拍| 亚洲精品国产精品乱码视色 | 亚洲视频人成在线播放| 一个人免费观看www视频在线| 在线观看免费视频一区| 日韩在线观看免费| 亚洲午夜精品久久久久久app| 亚洲第一福利视频| 亚洲日韩精品一区二区三区无码| 国产精品va无码免费麻豆| a毛片基地免费全部视频| 日本免费一区二区三区四区五六区| 一级做a爰黑人又硬又粗免费看51社区国产精品视 |