Note: I’ve been sitting on this one for a week. I don’t want to be misunderstood, Ruby is my second favorite language, and it has a lot to love. But I keep coming back to Python, and I think I know why. So, here goes:
Yesterday Last Week, I in response to a post by Dave Thomas, I wrote about optimizing for readability.
Dave Thomas post basically amounts to an homage to Ruby at the expense of Perl.
Dave likes Ruby because it is far more readable, and therefor more maintainable than Perl. So far I’m totally on the same page. Readability is critical to maintainability and extensibility, and that’s where most of the work on any successful software project is going to be done.
But, here’s where we part company at least a little bit.
I happen to prefer Python over Ruby because optimizing for readability is much more a part of the philosophy behind Python. Most of the lines from the Zen of Python have readability implications:
Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it.
Ruby makes better choices than Perl
But the language is still built around something they call “the principle of least surprise,” and the least surprised person here is the initial developer, not the code reader.
In practice means that there are several different names for the same array methods, and many array methods that are only slightly different from one another. If you are familiar with another language’s way to do it, the “least surprising” thing would be for that same method to just work on Ruby arrays right?
And this can make it easier to get started with Ruby. But there’s a downside, when reading Ruby code this means you may need to learn and remember all 78 different array methods. Some of them are obvious, .last will give the last element in the array. No worries there, and I like humane interfaces which give you easily understood and convenient functions, but this is just one example of how Ruby takes it too far, by forgetting that you will eventually have to figure out what eacy of those functions does in somebody else’s code.
Quick Ruby Quiz:
- is there a difference between array.size and array.length ? (no)
- How about array.map! and array.collect! ? (no)
- What about array.delete_if and array.reject ? (yes, reject returns nul if no changes are made)
- And for extra credit, why is there an array.collect (non-destructive) and an array.collect! (destructive) but not an non-destructive version of array.map! ?
I’ve been reading more Rails code recently, and while I like Ruby, and I admire Rails, I find myself constantly wishing I could hold more of this stuff in my head. I learned to write Ruby pretty quickly, but reading other people’s code has taken longer — just because there are lots of nooks and crannies in the built-in classes and modules that will take me a while to learn.
But Python makes better choices than Ruby:
Don’t get me wrong, I like Ruby. And it’s not particularly difficult to read. But the philosophy of the language designers led to design choices that emphasize writability over readability. And in that department I think the advantage has to go to Python. Python lists are easy to use, but more importantly I understood all of the list methods and how to use them in the matter of a few min. Perhaps Ruby’s arrays are more powerful that Python lists, but so far I’ve yet to find something that can be done in Ruby that can’t be done easily in Python.
I mean, think about it — even the things people complain about in Python, like the explicit self or significant whitespace, are designed to with readability in mind.