From: "Ara.T.Howard" Date: 2003-10-09T02:49:42+09:00 Subject: Re: map/collect iterating over multiple arrays/arguments On Wed, 8 Oct 2003, quent wrote: > zoranlazarevic@yahoo.com (Zoran Lazarevic) wrote in message news:<32c0bb6a.0310071950.55c75dd0@posting.google.com>... > > > Apparently it is not possible to iterate using Collection.each over > > multiple collections. It is possible by using one thread per > > collection, but I do not want to go there. > > a continuations multi_each has been placed on the wiki at rubygarden.org > if you are interested heres another one. it also defines an iterator class: ----CUT---- module Enumerable class Iterator public attr_reader :enumerable, :has_next def initialize enumerable, end_value = nil, &end_block @enumerable = enumerable @end_value = end_value @end_block = end_block initialize_fetch_block end def next @has_next ? fetch_next_element : fetch_end_value end def rewind initialize_fetch_block self end protected def initialize_fetch_block callcc do |@after_fetch| @has_next = true @enumerable.each 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 # enumerable instance methods def iterator; @iterator = Iterator.new self; end # enumerables class methods 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 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]] ----CUT---- -a ==================================== | Ara Howard | NOAA Forecast Systems Laboratory | Information and Technology Services | Data Systems Group | R/FST 325 Broadway | Boulder, CO 80305-3328 | Email: ara.t.howard@noaa.gov | Phone: 303-497-7238 | Fax: 303-497-7259 | The difference between art and science is that science is what we understand | well enough to explain to a computer. Art is everything else. | -- Donald Knuth, "Discover" | ~ > /bin/sh -c 'for lang in ruby perl; do $lang -e "print \"\x3a\x2d\x29\x0a\""; done' ====================================