它可能是一個有點混亂,不過要注意的是,在Ruby中的Enumerator
類和Enumerable
是非常重要的模塊。
的Enumerator
類包括Enumerable
(最喜歡的可枚舉的對象,如Array
,Hash
等
的next
方法被提供作爲Enumerator
,這的確有一個內部狀態的一部分,用戶可以考慮一個Enumerator
非常接近Iterator
其他語言暴露的概念。
當你實例枚舉器,內部指針指向集合中的第一項。
2.1.5 :021 > a = [1,2,3].to_enum
=> #<Enumerator: [1, 2, 3]:each>
2.1.5 :022 > a.next
=> 1
2.1.5 :023 > a.next
=> 2
這不是枚舉器的唯一目的(否則它可能會被稱爲Iterator
)。但是,這是記錄的功能之一。
枚舉器也可以用作外部迭代器。例如,#next返回迭代器的下一個值,或者如果枚舉器在最後,則引發StopIteration。
e = [1,2,3].each # returns an enumerator object.
puts e.next # => 1
puts e.next # => 2
puts e.next # => 3
puts e.next # raises StopIteration
但正如我前面所說的,Enumerator
類包括Enumerable
。這意味着Enumerator
的每個實例都會暴露Enumerable
設計用於集合的方法。在這種情況下,集合是Enumerator
所包含的集合。
take
是一種通用的Enumerable
方法。它旨在返回來自enum
的前N個元素。請注意,enum
指的是包含Enumerable
而不是Enumerator
的任何通用類。因此,take(2)
將返回集合的前兩個元素,無論指針在Enumerator
實例內的位置如何。
讓我告訴你一個實際的例子。我可以創建一個自定義類,並執行Enumerable
。
class Example
include Enumerable
def initialize(array)
@array = array
end
def each(*args, &block)
@array.each(*args, &block)
end
end
我可以混合Enumerable
,只要我爲each
提供實現我得到所有其他方法免費,包括take
。
e = Example.new([1, 2, 3])
=> #<Example:0x007fa9529be760 @array=[1, 2, 3]>
e.take(2)
=> [1, 2]
正如所料,take
返回前2個元素。 take
忽略了我實現的任何其他內容,完全與Enumerable
一樣,包括狀態或指針。
請[閱讀此](https://bugs.ruby-lang.org/issues/10534) – 2015-02-10 18:22:57
然後再讀一遍,,,有答案。 **請注意,+ next +不會影響其他非外部枚舉方法,除非底層迭代方法本身具有副作用,例如:IO#each_line。** – 2015-02-10 18:34:17