I program in both Ruby and Python and love both languages. Python is great because it fast and easy for most developers to understand, but when it comes to building great expressive DSL‘s my heart is with Ruby, well most of the time.
I have been doing some shared hacking on Ruby DSL project with a friend of mine. He is a very experienced C/Python developer, but fairly new to Ruby.
Yesterday, he pinged me with a question:
“Carlos, I have a dumb question, that is pissing me off, how do you do simple string replacement in Ruby?”
I was surprised by such a simple question, I told him use str.tr, which returns a translated string. He replied:
“What the fuck, tr?? Why doesn’t str.replace do that, I never would have thought that str.tr would mean in string replacement!”
It was funny being that I am equally fluent in both Ruby & Python I never gave it much thought that tr was not obvious in what it did, even though when I program in Python I would use replace to do the same string operation.
Let’s look at terminal:
~ $ python Python 2.5.1 (r251:54869, Apr 18 2007, 22:08:04) [GCC 4.0.1 (Apple Computer, Inc. build 5367)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> py = "The Python Way" >>> py = py.replace(" ", "_") >>> py 'The_Python_Way' ~ $ irb irb(main):001:0> rb = "The Ruby Way" => "The Ruby Way" irb(main):004:0> rb = rb.replace(" ", "_") ArgumentError: wrong number of arguments (2 for 1) from (irb):4:in `replace' from (irb):4 from :0
Simple string replacement in Python is very intuitive, but in Ruby str.replace replaces the entire string with another string. Now that may seem correct, but in most situations you are looking to do a find and replace within the string. So to make it work we do this:
irb(main):002:0> rb = rb.tr(" ", "_") => "The_Ruby_Way"
He was a little disappointed, because he was use to Python methods not being the most self documenting, but he did not expect that in Ruby. I told him that Ruby has it share of strange names and dups that do the same operation.
I told him to not despair that we could make his code more self documenting. One of the cool things about Ruby is that classes are never closed, so with a little sprinkle of spice we can do:
irb(main):006:0> class String irb(main):007:1> def find_replace(find, replace) irb(main):008:2> self.tr(find, replace) irb(main):009:2> end irb(main):010:1> end => nil irb(main):011:0> rb = "The Ruby Way" => "The Ruby Way" irb(main):012:0> rb = rb.find_replace(" ", "_") => "The_Ruby_Way"
My friend now loves Ruby.