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

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

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

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理

    Ruby Fiber指南(四)迭代器

    Posted on 2010-03-12 12:48 dennis 閱讀(3279) 評論(0)  編輯  收藏 所屬分類: 動態(tài)語言 、my open-source

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

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

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

    #全排列的遞歸實現(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ù)組中的每一個元素放到最后,依次遞歸生成所有剩余元素的排列,沒完成一個排列就打印出來。很顯然,這里有消費者和生產(chǎn)者的關(guān)系存在,生產(chǎn)者負(fù)責(zé)產(chǎn)生排列,消費者負(fù)責(zé)打印任務(wù),整個程序由消費者驅(qū)動,因此用Fiber改寫如下:

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

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

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

    while a=it.call
       printResult(a)
    end

        注意到,在perm方法中有一個很常見的模式,就是將對Fiber的resume封裝在一個匿名函數(shù)內(nèi),在lua為了支持這種模式還特意提供了一個coroutine.wrap方法來方便編程,在Ruby Fiber中卻沒有,不過我們可以自己實現(xiàn)下,利用open-class的特性實現(xià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)建一個新的Fiber,但是返回的是一個匿名函數(shù),這個匿名函數(shù)負(fù)責(zé)去調(diào)用fiber的resume,利用wrap改寫perm方法變得更簡潔:
    def perm(a)
      Fiber.wrap{ permgen(a,a.size) }
    end

        但是還不夠,while循環(huán)的方式還是不夠優(yōu)雅,每次都需要明確地調(diào)用迭代器的call方法,這一點讓人挺不舒坦,如果能像for...in那樣的泛型循環(huán)就好了,我們知道Ruby中的for...in其實是一個語法糖衣,都是轉(zhuǎn)變成調(diào)用集合的each方法并傳入處理的block,因此,要想實現(xiàn)一個優(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)建一個迭代器FiberIterator:
    def perm(a)
      FiberIterator.new{ permgen(a,a.size) }
    end
    這樣一來我們就可以通過for...in來調(diào)用迭代器了

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


       

        
    主站蜘蛛池模板: 亚洲伊人久久成综合人影院| 成人亚洲网站www在线观看| 亚洲看片无码在线视频| 无码中文字幕av免费放dvd| 亚洲va无码专区国产乱码| 花蝴蝶免费视频在线观看高清版 | 中文字幕无码毛片免费看| 亚洲中文字幕丝袜制服一区| 国产精品九九久久免费视频| 亚洲区小说区激情区图片区| 无码国产精品一区二区免费3p| 亚洲国产精品综合一区在线 | 国产高清对白在线观看免费91| 久久久久久亚洲精品不卡| 久久精品免费观看| 亚洲激情电影在线| 在线视频免费观看www动漫| 老司机午夜在线视频免费观| 国精无码欧精品亚洲一区| 久久久久高潮毛片免费全部播放| 亚洲人成777在线播放| 午夜免费福利在线观看| 麻豆安全免费网址入口| 黑人精品videos亚洲人| 色se01短视频永久免费| 久久精品国产亚洲av品善| 亚洲色大成网站www永久一区| 91av免费观看| 久久亚洲精品高潮综合色a片| 精品国产日韩亚洲一区| 5g影院5g天天爽永久免费影院| 亚洲中文字幕一二三四区| 精品亚洲一区二区三区在线观看| 日韩av无码久久精品免费| 亚洲欧美成人一区二区三区| 亚洲精品久久久www| 最近免费中文字幕高清大全| 青青免费在线视频| 亚洲自偷自拍另类图片二区| 五月婷婷亚洲综合| 免费无码又爽又刺激高潮视频|