Wednesday, April 23, 2008

Ruby's Achilles heel...

Ruby is a beautiful language. Far more beautiful, in my very subjective opinion, than Python. However, beauty, as they say, is only skin deep. Below the skin lies the equally important bits: implementation, documentation, portability, performance and more.

I will expound my findings "beneath the skin" in future posts, but I ran across something today so telling of my general experience, syntax aside.

Look at these two urls. Both are from the official* standard library documentation for the respective language.

Absolutely no comparison. Python functionality is documented clearly...Ruby's documentation amounts to a method prototype and nothing more.

While this is just one example, I've run across it sooooooooo many times in the last three years. It's such a sad state of affairs that the official Ruby web site doesn't even *have* a documentation section of its simply links to a collection of tutorials and third-party docs., which I pulled the above link from, takes the same approach, but includes the generated rdoc for the core and std libs. This rdoc is often, as demonstrated above, simply empty method prototypes.

It's simply tragic that such a useful and appealing tool has such shoddy documentation.

Tuesday, April 15, 2008

Functions versus blocks

In response to my last thread, someone answered with the following:

A problem I have with Ruby is that it has been infected with the same "everything must be in a class" nonsense that Java has. OOP is great, but sometimes having free-standing functions are more useful, especially functions that can be be applied to unrelated classes. "len" is a good example of this - because len is a function and not a method you can do things like this:

>>> x = ['abc', [1,2], () ]
>>> map(len, x)
[3, 2, 0]
>>> sorted(x, key=len)
[(), [1, 2], 'abc']
If 'len' was a method you would only be able to do this if all the objects that you want to take the length of inherited the 'len' method from a common base class (or mixin, in Ruby). This goes against the whole idea of duck typing.

So in this Python example, if I'm understanding it (and my Python studies) correctly, len is simply a reference to the function "object" that encapsulates logic that determines the length of something. Here's the official definition from the Python docs:

Return the length (the number of items) of an object. The argument may be a sequence (string, tuple or list) or a mapping (dictionary).

Ok, so the logic contained in the function object pointed to be the reference "len" gives us the ability to determine the length of a string, tuple, list or dictionary. Great.

Why though is this any better than Ruby? To do the same thing in Ruby, you'd do something like:
irb> x = ['abc', [1,2], {} ]
irb> {|one| one.length rescue nil}
[3, 2, 0]
So in the Python version, len is a builtin function that is passed to Ruby, I simply create a block and pass it to map.

Perhaps the poster didn't realize you can use rescue in this way? It allows you to call length on *any* object and returns nil if that method exists. You could also do: {|one| one.respond_to? :length ? one.length : nil }
I'm sure one performs better than the other under the sheets, but I haven't tested to verify.

Is Ruby's approach better than Python? In this simplistic example, probably not. However, I think that Ruby's block syntax is more explicit and indicates meaning at the point of usage. Let's say I wanted to do more than just return length...what if I wanted to do some type checking as well?

In Python, I'd have to create a method first to wrap the desired functionality:
def conditional_len(obj):
if isinstance(obj, list):
return len(obj)
return None

a = [1, [2, 3], 4]
map(a, conditional_len)
In Ruby, it's (IMO) more obvious what we're trying to accomplish:
a = [1, [2, 3], 4] do |one|
if one.is_a? Array
return a.length
return nil
So I'm not sure I follow the argument here. Why exactly is Python's way advantageous compared to Ruby's? Can anyone shed some light?

Tuesday, April 8, 2008

Why I want to use Python, but don't...(yet)

Hello. I appreciate you stopping by. Let me tell you why this blog is here.

I'm a long-time developer. I have roughly 8 years of professional developer experience. I still read things daily by others that leave me in awe, but I think I hold my own pretty well. In other words, I'm good, but I haven't become so arrogant and obnoxious that the rest of the world look like idiots.

The road to here for me has been:

ksh -> C -> Perl -> C++ -> Java -> Php -> Java -> Ruby

I spent around three months doing Python in between Php and the second Java stint. I liked was ok. But, the profession had other ideas for me.

It's been a fun ride. I've really appreciated things about each language I've used. But I finally found something in Ruby that really clicked. The language was intuitive; it could easily be held in your head, and what couldn't could be found quickly by exploring its very solid (though not perfect) introspection capabilities. There was a bit of a curve regarding rails, but that wasn't Ruby's fault...Ruby was just pretty ('cept for those damned dangling ends).

I really like Ruby the language...Ruby the experience...not as much. The docs are really bad right now in general across the Ruby space (I presume this will improve). The implementation is slow, but I honestly haven't done anything popular enough to feel threatened by it. Many of the libraries I need (eventmachine) are immature at this stage.

So many things lately have been pushing me towards Python. First, twisted has all the features I need for the network programming I'm working on. Second, I've read some really good things about Django and Pylons, and am preparing to work on a new web app. Third, Google's release of app engine today provides what I would consider some very strong validation for the Python community and for Python as a web programming language. Woohoo.

I actually started re-learning python a few months ago when I needed what Twisted had, but God help me I choked on the language itself. So many inconsistencies (__builtins__, two object models, .join, etc) that just didn't add up to a language with the beauty of Ruby.

I read the tutorial, bought Python in a Nutshell, read many of those chapters. But wow....I mean, really...Python seems so much more complex than Ruby. The chapter on OOP alone in Python in a Nutshell really twisted my head. And I've been doing OOP for years! Instead of a language like Ruby that you can entirely keep present in brain "ram", Python seems like a language that causes a significant amount of "swapping". In fact, I wonder if most Python programmers keep (or even understand) a very small subset of the language and operate in that space only. (which, if true, is complimentary to the language).

Listen, I want to explore Python. I want to want to use it. Right now I'm only driven by the fact that its libraries are solid and well documented, its implementation is fast, and it is widely used by two things I love (Linux and Google). If Ruby were in the same boat, there'd be no motivation to move. If Ruby had well-documented libraries (some day?), a good VM (soon) and was proven in big environments, I wouldn't be writing this.

So, here's my arm...please twist it. Help me to understand why Python is the way it is. Help me grok why people like it and use it so much. Help me understand why .join is where it is ( chance in that). Help me feel good about investing the effort in to master Python. I want to join the community, but can't help but feel hesitant.