文章1-4篇說的都是js中的可疊代對象,下面讓我們看看ruby中的等價物。
不可否認,ruby中對于疊代器和生成器的文法都相當簡潔;ruby從一開始就有一個簡潔的基因,而js後來的不斷擴充使得其有些文法比較“别扭”和“奇怪”,雖說ruby也不比js小幾歲啊!(官方的說法是一個1992年一個1995年)
在ruby中周遊一個數組的代碼如下所示:
而在ruby中範圍對象本身是可枚舉的(可周遊差不多意思),是以你可以直接這麼寫:
在ruby中寫一個疊代器,也是相當簡單:
而ruby中的枚舉器和js中的可疊代對象類似,枚舉器是類enumerable::enumerator的執行個體,一般通過object類的to_enum或其同義詞enum_for方法來建立連如果調用時沒有提供參數則to_enum傳回一個枚舉器,該枚舉器的each方法隻是簡單調用目标對象的each方法,枚舉器的一個用途是建立防禦式拷貝:
如果to_enum中第一個實參是一個符号,則它辨別了一個疊代器方法,枚舉器的each方法調用那個疊代器方法:
而在ruby1.9之後又對枚舉器的文法做了修改使其更加簡潔,當以不帶代碼塊的方式調用内建疊代器方法時,會自動傳回一個枚舉器,是以上述代碼可以簡寫為:
要想對自定義的疊代器方法實作如上行為,可以通過傳回self.to_enum來實作:
簡單解釋下self.to_enum(:itor,x)這句,因為我為了測試友善是在全局上下文中定義的函數itor,是以它自動成為全局對象main的私有方法,而該方法也會成為object類的私有執行個體方法:
在執行self.to_enum(:itor,x)時,當時的self是main對象,即将傳回枚舉器的each方法與itor函數對應上。
ruby裡面也有類似的for in循環,不過我們一般都不怎麼用呢:
枚舉器可以實作外部疊代,實際上枚舉器也稱為外部疊代器。可以使用kernel.loop方法包裹枚舉器,進而在stopiteration異常抛出時自動退出循環:
在ruby中枚舉器自帶了rewind方法使外部疊代器重新開始疊代。
最後,在ruby中我們可以用纖程(fiber)來實作所謂的生成器,雖然這比較晦澀: