In article <f04d2210909251312q46bd51c0teacc4b0a8c417f0c / mail.gmail.com>, Charles Oliver Nutter <headius / headius.com> writes: > So the small problem with Enumerator#next is that it's slow on MRI > because of continuations and slow on JRuby because of native threads. I thought this slowness sometimes ago. STDIN.lines.next is basically same as STDIN.gets or raise StopIteration but it has overhead of Fiber. IO has already a method for external iteration method (gets) but IO#lines cannot use it. I think Enumerator.new (and possibly to_enum, enum_for) should be able to take an array consists of two method names for internal and external iteration as: Enumerator.new(obj, [method1, method2], *args) method1 is for internal iteration and method2 is for external iteration. The enumerator created by Enumerator.new uses method2 when next method is called if method2 is provided. obj.method2 should return an object for external iteration. If Enumerator.new provides such way to avoid Fiber, IO can use it as: class IO def lines Enumerator.new self, [:each_line, :external_iterator_for_lines] end def to_enum(meth=:each, *args) if meth == :each || meth == :each_line super [:each_line, :external_iterator_for_lines], *args else super end end def external_iterator_for_lines o = Object.new o.instance_variable_set(:@io, self) def o.next @io.gets or raise StopIteration end o end end This idea may solve some part of JRuby problem if a class provides custom to_enum. If a class don't provide that or user specify unexpected method name for to_enum, it still problem though. -- Tanaka Akira