class IteratorQueue
def initialize(obj=[])
unless obj.respond_to?(:each)
raise(ArgumentError, "no iterator(#{obj.class}#each)")
end
@body = []
obj.each do |item|
@body.push item
end
end
def enqueue; @body.shift; end
private
def IteratorQueue.deligate_method(member_symbol, method_symbol)
module_eval <<-EOS
def #{method_symbol}
@#{member_symbol}.#{method_symbol}
end
EOS
end
deligate_method(:body, :inspect)
deligate_method(:body, :empty?)
end
class OuterIterator
class IterateFinishError < RuntimeError
def message
'iterating already finished'
end
end
private
def inspect
"#<#{self.class}:#{self.object_id}>"
end
def initialize(obj=[])
obj = yield(obj) if block_given?
begin
@q = IteratorQueue.new(obj)
rescue ArgumentError => ex
raise(ArgumentError, ex.message)
end
end
public
def more?; !@q.empty?; end
def next
raise IterateFinishError if @q.empty?
@q.enqueue
end
end