From: "Ara.T.Howard" Date: 2004-08-04T01:31:33+09:00 Subject: Re: Request for two methods in Array class On Wed, 4 Aug 2004, Claus Spitzer wrote: > That's a strong point. Elaborating a bit more on that, perhaps what is > needed is not a new method (or a collection of them), but a way of piping > objects instead of creating intermediate ones. Then methods could be still > chained, but with better spatial efficiency. > -CWS generic iterator functionality will give something close to this - using the example the OP gave: ~/eg/ruby > cat a.rb require 'enumiter' a = 1,2,3 b = 1,3,5 prod = Enumerable.map(a,b){|x,y| x * y} p prod ~/eg/ruby > ruby a.rb [1, 6, 15] a sample impl of enumerable iterators and assoc Enumerable.each/map/collect: # # iterator and multi-each/collect support for enumerables # module Enumerable #{{{ # # generic callcc based iterator wrapper class for enumerables # 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 # # additional enumerable instance methods # def iterator; @iterator = Iterator.new self; end # # additional enumerable module methods # # 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]] regards. -a -- =============================================================================== | EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov | PHONE :: 303.497.6469 | A flower falls, even though we love it; | and a weed grows, even though we do not love it. | --Dogen ===============================================================================