標籤:
迭代器
一個迭代器是一個方法,這個方法裡面有yield語句,使用了yield的方法叫做迭代器,迭代器並非一定要迭代,與傳遞給這個方法的塊進行資料轉送
yield將資料傳給代碼快,代碼塊再把資料轉送給yield
each方法就是一個迭代器,裡面有yield語句
列舉程式
1 一個列舉程式是Enumerable::Enumerator的一個對象,Enumerable是一個模組
2 使用列舉程式 1.8的時候需要 require ‘enumerator‘,在2.1就不用了
3 可以通過new來執行個體化一個列舉程式,但是通常使用Object類的to_enum或enum_for,返回一個列舉程式,這個列舉程式只是簡單調用目標對象的each方法,這句話意思就是說例如 a.to_enum執行後返回一個列舉程式,這個列舉程式的each方法會調用a對象的each方法
4 當給to_enum傳遞一個符號參數和其他參數的時候,或者使用enum_for語義上更好例如
a.enum_for(:bbb,arg1,arg2),這個:bbb是一個迭代器方法來自a對象,enum_for方法返回一個列舉程式,這個列舉程式有一個each方法,這個each方法調用上面a對象的迭代器方法就是這個:bbb方法,把其餘參數arg1,arg2傳遞給那個迭代器:bbb
例如String類不是Enumerable的,但是String類自身有三個迭代器方法(方法裡有yield,這三個是String的方法,不是Enumerable的) each_char each_byte,each_line,我們想使用一個enumerable方法,比如map,
s = "hello"
s.enum_for(:each_char).map {|c| c.succ}
eg:
class Test1
include Enumerable
def hello(a,b)
yield a+b
end
end
a = Test1.new
b =a.enum_for(:hello,1,2)
b.each do |x|
p x
end
或者
a.enum_for(:hello,1,2).select {|x| puts x}
5使用情境,當一個類A ,include Enumerable時候。A的執行個體對象就具備了Enumerable裡的方法,當我們 a = A.new後, a.enum_for(:xxx)就返回了一個列舉程式,這個列舉程式的each方法調用這個xxx方法,而這個xxx方法就是A類裡的一個迭代器方法,這樣就可以a對象調用enumerable裡的方法,同時傳遞一個代碼快例子如下
class Test1
include Enumerable
def hello(a,b)
yield a+b
end
def each(a,b)
yield a+b
end
end
a = Test1.new
b =a.enum_for(:hello,1,2)
b.select do |x|
p x
end
6 在1.9,2.1中應該也是一樣,不需要顯示的調用to_enum或者enum_for,當不用代碼塊調用內建的迭代器(內建迭代器指的是times,upto,downto,step.each及Enumerable的相關方法)的時候,就是指a.enum_for(:each)這句執行但是沒有傳遞代碼快,不傳遞代碼快的話就自動返回一個列舉程式
a.each 這個就會返回一個列舉程式
按照6所說的,上面執行個體代碼 b =a.enum_for(:hello,1,2) 這行就省略了。直接
a.each do |x|
p x
end
前提是A類裡必須有一個each的迭代器方法
class Test1
include Enumerable
def each
yield 3
end
end
a = Test1.new
a.select do |x|
p x
end
有些內建類自身實現了 each方法,才可以 按照6所說的那麼做,如果我們自訂一個類,沒有實現 each方法,不可以省略.enum_for
ruby迭代器列舉程式