From: Eric Hodel Date: 2005-10-27T16:54:34+09:00 Subject: Re: Enumerable#build On Oct 26, 2005, at 4:47 AM, Robert Klemme wrote: > Martin DeMello wrote: > >> class Enumerable >> def build(seed) >> each {|i| >> seed.add(yield i) >> } >> end >> end >> >> and >> >> Array#build == Array#<< >> Hash#build(k,v) == Hash#[] >> etc >> >> So you could say [1,2,3].build({}) {|i| [i, 1]} for the question that >> prompted the to_hash thread, but also, in general, you can collect >> into non-array structures (binary trees, e.g.) as long as they >> implement a suitable #add method. >> >> (Of course, you can do ary.inject(seed) {|i| seed.add(f(i)); seed} >> right now but a #build method makes the common case pretty.) >> > > Looks good. But, > > - Enumerable is a module... :-) > > - You should add seed as return value. > > - Your first example won't work as Hash#add is nonexistent > > An alternative approach would be to reverse the logic and have > Enumerable#populate: > > module Enumerable > def populate(*enum) > enum = enum.first if enum.size == 1 > enum.each {|*a| add(yield(*a))} > self > end > end > > class Hash > def populate(*enum) > enum = enum.first if enum.size == 1 > enum.each {|*a| send(:[]=, *yield(*a))} > self > end > end > > >>> h={}.populate(1,2,3) {|x| [x, "val #{x}"]} >>> > => {1=>"val 1", 2=>"val 2", 3=>"val 3"} > > What do you think? I think you have too much magic. Enumerable#to_a, Array#fill, Array#flatten and Hash::[] do this pretty handily and much more cleanly: Hash[*ary.fill { |i| [i, "val #{i}"]}.flatten] $ ruby -e 'p Hash[*(0..3).to_a.fill { |i| [i, "val #{i}"] }.flatten ]' {0=>"val 0", 1=>"val 1", 2=>"val 2", 3=>"val 3"} -- Eric Hodel - drbrain@segment7.net - http://segment7.net FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04