From: Robert Klemme Date: 2005-04-08T06:54:40+09:00 Subject: Re: help traversing and modifying hash key and value inplace "Trans" schrieb im Newsbeitrag news:1112899357.671275.91150@o13g2000cwo.googlegroups.com... > Having a little trouble here. seems that I'm getting some errors trying > to dup certain values (like FIXNUM), or if I try clone it says that I > can't modify a frozen string. Is there a way to achieve this > functionality? Here's the code: > > class Hash > > # Returns a new hash created by traversing the hash and its > # subhashes, executing the given block on each key/value pair. > # > # h = { "A"=>"A", "B"=>"B" } > # h = h.traverse { |k,v| k.downcase! } > # h #=> { "a"=>"A", "b"=>"B" } > # > def traverse( &yld ) > h = {} > self.each_pair do |k,v| > q = k.dup > f = v.dup > if f.kind_of?(Hash) > h[q] = f.traverse( &yld ) > else > yield(q, f) > h[q] = f > end > end > return h > end > > end Unfortunately not all objects can be dupe'd or cloned. I wished that #dup would return self in these cases but Matz decided to do it otherwise (both alternatives have their merits). You need special treatment for that to work. Alternatively use Marshal. Another problem of your implementation is that it doesn't take recursive structures into account. I also find the copying of values inside the method sub optimal: there might be cases where you don't want or need copies (for example if you add 1 to all keys and values, which creates new instances anyway). So I'd leave the copying to the discretion of the block. If I wanted to do the conversion you did, I'd probably do this: h.inject({}){|h,(k,v)| h[k.downcase] = v; h} (Yes, I know these are not exactly equivalent.) Just some 0.02EUR... Kind regards robert