From: Brian Candler Date: 2008-10-28T17:38:26+09:00 Subject: Re: Hash.merge_add! extension - how does this code look? Greg Hauptmann wrote: > interesting - is it really Ruby approach to let things 'break' during > a method so to speak Generally speaking, yes it is. Depending on your implementation, you probably only make use of a one or two Hash methods - says 'keys' and '[]' By not testing the class, you allow other objects which also implement these methods to work, which typically makes your code more useful. If you wanted to be really anal, you could do: raise "Unsuitable object (doesn't implement 'keys')" unless hash.respond_to?(:keys) raise "Unsuitable object (doesn't implement '[]')" unless hash.respond_to?(:[]) However the error message you would then generate would be almost identical to the default Ruby one: > "" Now, in this particular case, I'd say an ideal API would only depend on 'each', and then it could be used for any enumerable object which yields two values. For example: class Hash def merge_add!(h) h.each do |k,v| if has_key?(k) self[k] = Array[self[k]] + Array[v] else self[k] = v end end end end tmp = {"one"=>1, "two"=>2} tmp.merge_add!([["three",3], ["one",999]]) p tmp I should add that I don't like the fact that the resulting hash will have a mixture of array and non-array values, as it makes the values harder to use later. If it were me I'd want all the values to be arrays. A similar case I have come across before is a multi-valued Hash#invert, where different keys map to the same value. # input: {"foo"=>1, "bar"=>1, "baz"=>2} In that case, what I would want is # output: {1=>["foo","bar"], 2=>["baz"]} rather than # output: {1=>["foo","bar"], 2=>"baz"} -- Posted via http://www.ruby-forum.com/.