I am in general very fond of Ruby. It’s a very appealing language allowing all kinds of object-oriented designs not available in Java and other traditional languages. However, there is no such a thing as a perfect language, and there are a few details in Ruby that bother me. For example:
- The Perl heritage. Ruby uses variables named $`, $’, etc… This hacker parlor trick is the worst outrage you can inflict to a program. You are guaranteed to confuse anyone who isn’t intimately familiar with Perl if you use these variables. Luckily, a module called “english.rb” allows you to use more meaningful names, but not everyone uses it.
- The end keyword. I am a big fan of meaningful indenting, such as in Python. It bothers me when I read a source and suddenly, I see five “end” words next to each other in decreasing indentation. This is visually unpleasant and clutters the code. And if visually indenting is not an option, at least “}” is not as verbose as “end”, which I just can’t help spelling in my mind when I read it, even though it doesn’t add much to the semantics of the code.
- No overloading. That’s right. If you want overloaded methods, you need to declare one method with a varargs signature and decide what code to invoke based on the types of the objects that were passed. This omission boggles my mind, but it’s perfectly in line with Matz’ philosophy, who is a strong opponent of orthogonal features because they tend to “explode into complexity”.
Matz does have a point with the exploding complexity of orthogonal features. I believe this fact is one of the main reasons why C++ became so unbelievably complex, both in syntax and in semantics. For examples, templates were initially introduced using the “<" and ">” characters. It didn’t take long before somebody realized that this new notation would conflict with the stream operator “>>”, thereby forcing you to close nested templates with “> >” instead of “>>”.
However, I believe that in the particular case of overloading, Matz is mistaken. This is one of the few features whose combination with other features is pretty well understood and still easy to read. The only problem I can think of is when you try to mix overloaded methods with default arguments. The ambiguity of this particular case led to the rule that default arguments can only be specified at the end of the signature (okay, there is another reason for this constraint that has to do with the way parameters are pushed to the stack, but I won’t go there).
Matz himself is the first to say that “there is no perfect language”. Or rather, his perfect language is not my perfect language. Fair enough.
Ruby is still a joy to program.