to_enum是Object类的实例方法,有以下两种调用方式(可参考ruby api文档):

obj.to_enum(method = :each, *args) → enum
obj.to_enum(method = :each, *args) {|*args| block} → enum


to_enum会返回一个Enumerator,其内部的迭代方法就是调用这个method,默认method是each。

示例:

[18] pry(main)> class B
[18] pry(main)*   def iter(&block)
[18] pry(main)*     pp :abcdefg
[18] pry(main)*     return to_enum unless block
[18] pry(main)*     (6..12).each(&block)
[18] pry(main)*   end
[18] pry(main)* end
=> :iter
[19] pry(main)> B.new.to_enum
=> #<enumerator: ...="">
[20] pry(main)> B.new.to_enum.map{ |e| e + 1 }
NoMethodError: undefined method `each' for #
from (pry):38:in `each'
[21] pry(main)> B.new.to_enum(:iter).map{ |e| e + 1 }
:abcdefg
=> [7, 8, 9, 10, 11, 12, 13]
[22] pry(main)> B.new.to_enum(:iter).to_a
:abcdefg
=> [6, 7, 8, 9, 10, 11, 12]</enumerator:>


顺提,在Enumerator对象上调用to_a,可以认为是:

arr = []
enum.each{ |e| arr << e }
return arr


调用to_enum时带block,则会在调用Enumerator#size时直接使用block的运行结果,而非迭代计数

[16] pry(main)> en = [1,2,3].to_enum{2}
=> #<enumerator: ...="">
[17] pry(main)> en.size
=> 2</enumerator:>