On Tue, 8 Aug 2006, vasudevram wrote:
Thanks
Vasudev
here’s some code that uses it to impliment external iterators in ruby,
may be
helpful:
module Enumerable
class Iterator
public
attr_reader :enumerable, :has_next
def initialize enumerable, meth = ‘each’, end_value = nil,
&end_block
@enumerable = enumerable
@meth = meth
@end_value = end_value
@end_block = end_block
initialize_fetch_block
end
def next
ret = @has_next ? fetch_next_element : fetch_end_value
(ret.nil? ? ret : (ret.size == 1 ? ret.first : ret))
end
def rewind
initialize_fetch_block
self
end
protected
def initialize_fetch_block
callcc do |@after_fetch|
@has_next = true
@enumerable.send(@meth) do |*@next_element|
callcc do |@next_fetch| @after_fetch.call end
end
@has_next = false
@next_fetch = nil
@after_fetch.call
end
@after_fetch = nil
end
def fetch_next_element
result = @next_element
callcc do |@after_fetch| @next_fetch.call end
@after_fetch = nil
result
end
def fetch_end_value
@end_block ? @end_block.call : @end_value
end
end
def iterator(*a, &b); Iterator::new(self, *a, &b); end
class << self
def each(*enumerables, &block)
iterators = enumerables.collect{|e| e.iterator}
while true
args = iterators.collect{|i| i.next}
if args.detect{|arg| arg}
block.call *args
else
return enumerables
end
end
end
def collect(*enumerables, &block)
ret = []
each(*enumerables){|*args| ret << (block.call *args)}
ret
end
alias map collect
def enumerate(enumerables, meth = ‘each’, *a, &b)
rets = []
iterators = enumerables.map{|e| e.iterator(*a, &b)}
iterators.each_with_index do |iterator, idx|
rets[idx] << iterator.next
end
rets
end
end
end
if $0 == FILE
#{{{
a = [‘fee’,‘fie’,‘foe’,‘fum’]
h = {‘k’ => ‘v’, ‘K’ => ‘V’}
ai = a.iterator
hi = h.iterator
while ((n = ai.next)) do
puts n.inspect
end
while ((n = hi.next)) do
puts n.inspect
end
Enumerable::each a, h do |elem, kv|
puts elem.inspect
puts kv.inspect
end
p Enumerable::collect(a,h){|e,kv| [e,kv]}
#}}}
end
END
OUTPUT:
“fee”
“fie”
“foe”
“fum”
[“K”, “V”]
[“k”, “v”]
“fee”
[“K”, “V”]
“fie”
[“k”, “v”]
“foe”
nil
“fum”
nil
[[“fee”, [“K”, “V”]], [“fie”, [“k”, “v”]], [“foe”, nil], [“fum”, nil]]
-a