Ruby 枚举器Enumerators (高级)

要让一个类可以枚举(Enumerable),那么就是需要他具有一个each方法。同时include Enumerable。(mixin模式)

String不是Enumberable的,因为他有三个迭代器(Iterator),但是不包含each。

each返回一个Enumerator,可以用它来外部访问进行枚举。例如

enu = my_array.each

enu.next #类似游标,获取元素

注意到尾部后继续next会返回一个StopIteration异常。

也可以通过获取该enumerator来直接调用map等函数。例如

"xyz".each_char.map{|x| puts x}  #等价于 "xyz".enum_for(:each_char).map

顺便说一句,enum_for和to_enum的实现完全相同。类似的还可以使用Enumberator.new。

Enumberator.new有两种形式:

new(size = nil) { |yielder| ... }

new(obj, method = :each, *args)

第一种的直接用block生成一个枚举器。例如

fib = Enumberator.new  do |y|

    y<<1

    y<<2

    y<<3

end

第二种其实就是将enum_for,to_enum的caller作为obj,参数即method,最后是参数。(这是ruby常用的调用方法的方法)

"string".to_enum(:each_char) 

等价于

Enumerator.new("string",:each_char)

自己构造类似Array的可枚举类型的时候,只需要实现each,然后

include Enumerable 

(module) 就可以实现map,select等枚举器。其实这些枚举器都是建立在each基础上的。

each的实现主要是使用yield,在each定义中循环执行 yield x #x当前变量。

在each的实现中,应该区分判断如果有block,block_given?就调用block,否则就返回一个Enumberator对象。

你可能感兴趣的:(Ruby 枚举器Enumerators (高级))