From: "David A. Black" Date: 2008-10-26T21:13:13+09:00 Subject: Re: Hash.merge_add! extension - how does this code look? Hi -- On Sun, 26 Oct 2008, Greg Hauptmann wrote: > Hi, > I wanted a way to be able to "add" values to a Hash such that it keeps the > old and the new values. For examples example adding an item to a hash for > which the keys are dates. Here's a first cut. Any feedback on coding > style etc? Just a quick (1/2-cup of coffee) point: > ================================ > class Hash > # Merges a hash with only one item into your hash. If there is already a > # hash entry for that key the both existing value(s) & new value are kept > via > # use of an Array > def merge_add!(h) That's not a good name for it, because there's no non-bang merge_add method. The ! in method names only makes sense (with very few, very specialized exceptions, like the way Jim W. uses them in Builder) if the methods come in pairs: one regular method and one "dangerous" method ("dangerous" being Matz's term to describe the meaning of the !). The reasoning is as follows. Bang method names never have, and never will, coincide completely with receiver-altering methods in Ruby. That's just not a possibility, and has never been envisioned. (Consider Array#pop, String#replace, and many, many more.) So adding a bang just because the receiver is being changed doesn't make sense, and dilutes the convention of the regular/dangerous pairing. Putting a bang on an unpaired method name just because the method seems "dangerous", in a unary way, doesn't make sense either. Rails does this, and it's about my least favorite thing about the Rails source code. If ! just means "This method does something dramatic!", we're back to a very fuzzy, uninformative, impressionistic use of !. Matz had it right: the regular/dangerous pairing of otherwise same-named methods is an incredibly creative and useful application of the bang. It actually tells you something. Every time people complain because gsub! returns nil if the receiver doesn't change, all I can think is: "You were warned! There's a bang in the name; that means it's similar to gsub but it's dangerous. Heads up! Go read the docs! Don't complain!" :-) In Ruby, unpaired methods always have names that already incorporate what they do and whether or not they change their receivers. Yes, there are some glitches (like Array#delete and String#delete being different as to receiver-changing). But Array#pop isn't Array#pop! because there's no possible non-destructive "pop"; that would just be array[-1]. So if you've got an unpaired method name and you feel like it's not communicating enough, it's best to change the name rather than add a !, for the reasons above. Anyway, that's the gist. Sorry to pounce on one thing. I'll have more coffee and look at the code itself :-) David -- Rails training from David A. Black and Ruby Power and Light: Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL Advancing with Rails January 19-22 Fort Lauderdale, FL * * Co-taught with Patrick Ewing! See http://www.rubypal.com for details and updates!