Tuesday, January 29, 2008

Ruby Backlash

I suppose it was about time. Ruby and Rails had been a little too highly touted, and now the backlash has begun. Zed's blog entry was the biggest slap to the Ruby/Rails communities, but there have been others.

I love Ruby. I have never found another programming language that has been as easy to use. I've played with Lisp. I've written some small utilities in Python. I've used PHP, Java, and Perl for production sytems. In terms of pure programming pleasure, the only language that has even come close for me is Rhino JavaScript.

As for Rails, I have my objections, but I have yet to find a framework that I like better. DHH hit on something, and there are a lot of frameworks out there that have been trying to copy the Rails formula. I've played with a number of others, but the ones I like best tend to follow Rails in the ease of DB access and the clean organization.

Ruby vs. Python
One common thread among the Ruby backlashers is "I already know Python". There is something to be said for this. When I started working with Ruby, I knew a little Python, but I was still just learning. If I had been introduced to Ruby a year later, it might be a different story. Python is an amazingly beautiful language, and it is hard to be wowed by Ruby after learning Python.

Nonetheless, there are a few places where I think Ruby shines in comparison.
  1. Regular expression support. I rely on regular expressions heavily. In data feed processing and linguistic work, they are a wonderful tool. Python has decent libraries, but... They feel tacked on. In Ruby, they are a core part of the language. Ruby is the only language I know that can go toe-to-toe with Perl in this area.
  2. Object-oriented syntax. This is a minor point, but Python's OO syntax has always kind of bugged me. Passing 'self' as the first parameter seems, well... pretty friggin' lame. You get used to it, drink the kool-aid, and then spend your time telling everyone that "it's not a bug, it's a feature". Ruby does not have this, um, feature.
  3. Erb (embedded Ruby). Equivalents to this exist in almost every major language these days, but the key distinctions of Erb is that it can be used from the command line. This is huge. For one example, I replaced a 2108 line XML configuration file with a 473 line erb file.
  4. Ruby blocks. Python is only getting bashed on this point because it is first in the list... The biggest thing I miss when using other languages is Ruby's ability to pass blocks of code. Blocks are closures, and this is huge. All of the boilerplate code that you can't avoid in other languages is easy to sidestep with Ruby. (Neal Gafter's proposal for closures in Java will bring the same benefits -- I hope he succeeds).
Now, to be fair, Python has some strengths as well. A real Python guru could probably add a few more, but these were the ones I noted from my Python experience.
  1. Whitespace sensitive. This is often listed as a criticism of Python, and I've never been sure why. I think there is a huge value in tying the actual logic of the program to its apparent logic. We use whitespace to organize things -- why shouldn't the computer follow suit? The arguments against this seem to be a) it makes embedded Python difficult and b) tabs v. spaces becomes a real problem. Point A seems valid, but there are a number of Python web-dev frameworks out there. They must have solved it somehow. As for B... If you open a file and edit it, but don't match the whitespace, you are getting off easy with broken code. Personally, I think it a hangable offense.
  2. No implicit returns. This is another minor point, but since I criticized Python for its OO syntax, it seems only fair to mention it. I don't like implicit returns. If I want to return something, I'll @#$! well type 'return'. I wish the rest of the Ruby community would too. It seems a bad idea to me that you are returning values when you might not mean to. What happens if others start relying on that behavior?
Ruby vs. Java/Perl
Matching Java and Perl may strike many as odd. However, Ruby combines some of the best of both worlds. On the other side, both Java and Perl have the advantages that come with being well-established, fire-tested, battle-hardened languages

What appeals to me about Ruby and Perl over Java:
  1. Great regex support. I mentioned this under Python already. Perl is king of regular expression support. I'm vaguely aware that Perl has some extras that Ruby does not, but I could not tell you what they are. The biggest difference that is noticeable is that regular expressions are objects in Ruby, which means you can set them as arguments, add methods to them, etc.
  2. Easy to experiment with. Any project I do becomes object-oriented when it hits a decent size. However, in Ruby and Perl I don't have to do so until I am ready. When I am experimenting, I can just start typing commands. When it gets a little larger, I can toss in a stand-alone function or two. When I have more that that, it is time to bring in the objects. You can't do that in Java. Your best bet then is to use BeanShell.
  3. Good support for hashes/arrays. In Java, there is some support for creating Arrays succinctly, but it is limited. There is no succinct way to create any kind of Map. In Java, you need a property file a lot sooner than you do for any other language.
What appeals to me about Ruby and Java over Perl:
  1. Simple syntax for objects. Perl's OO system is a bless-ed mess.
  2. Arrays of Hashes, Hashes of Arrays, etc. One surprising complication in Perl is getting a collection out of a collection. There are so many '$'s and '%'s that it looks like cartoon swearwords. I have to look the syntax up every time that I do it.
Where Ruby fails short of Java and Perl:
  1. Performance. Ruby is slow. Most of the time, this is not a factor for me... But not always. Once, I wrote a part of speech tagger in Ruby. I ran it on a large amount of data, and it took well over an hour to run. I ported the code to Java. The new program was 4 times the size, but ran in about 15 minutes, which I thought was a nice illustration of the strengths of both languages.
  2. Libraries. Java and Perl have a massive collection of libraries. Whatever you want to do, you can at least find one library for it. That is not always true for Ruby.
Off subject, but... Perl is the only language I know of that has not been ported to the JVM. There are JVM implementations of Ruby, Python, JavaScript, and a whole mess of Lisps. A huge number of new languages have been written for the JVM. Library support is always the key. Perl's support is every bit as good as Java's, so why would anyone bother?

Ruby vs. Rhino
These have become my two favorite languages. Both have rich metaprogramming features. Whenever I use one, I miss features from the other.

Where Ruby rocks:
  1. Blocks. JavaScript functions are closures, but it is not enough. As Neal Gafter would say, "you can't just slap a pair of curly-braces around it".
  2. Class-based object system. This is likely to change soon, but Rhino currently does not use a class-based object system. Prototypes are cool. I even took advantage of this to build a metaobject protocol for JS. However, classes are easier for programmers to understand. It is nice not to have to do the mind-shift to the world of prototypes. This is a minor point for me, but important for some.
  3. Server-side programming? Or maybe not... There is Helma and Phobos, and possibly one day we will actually get to see Rhino on Rails. Rails still seems to have more of the world's attention, but that could change.
Where Rhino tramples Ruby:
  1. JVM support. JRuby has been making rapid progress, and it could end up matching Rhino here one day. Maybe. But in a lot of small ways, JS is a lot closer to Java. Simple things like the use of CamelCase instead_of_underscores make Java programmers feel more at home.
  2. Getting/Setting unknown variables. In JS, you can get or set a property easily if you have the variable name in a string. This is doable in Ruby, but not as easily. You need to use the 'method' method and then use the 'call' method on the returned method:
    property_to_print = :bar
    f = Object.new
    def f.bar
    42
    end
    puts f.method(property_to_print).call

    In JS, we can do the same thing more easily:

    var propertyToPrint = 'bar';
    var f = {};
    f.bar = 42;
    print(f[propertyToPrint]);

    This seems somewhat trivial, but it comes up surprisingly frequently.


Ruby on Rails Vs. PHP
Ruby is overwhelmingly better as a general-purpose language. PHP is overwhelmingly better as a framework-less web development language. A more informative comparison is to compare Rails to PHP. But this is not really fair either. Rails is a framework, and PHP is a language. It would be more even to pit Rails against CakePHP or Zend. The fundamental problem here is that I don't know either of those frameworks. But so it goes.

PHP is unusual. It seems like half a language and half a web development framework. Initially I felt nothing but disdain for it, but I've been slowly coming to appreciate its strengths, particularly after reading "PHP in Action".

I do miss a number of Ruby's features when doing PHP. In particular, the lack of first-class functions is frustrating. PHP has create_function, but it is less than pleasant to use. Worse, it does not work for creating methods on the fly (at least not in PHP 5).

However, when it comes to creating an initial mockup, there is no language I like better. I have a Mac, and with PHP pre-installed, I can just start typing html, embedding chunks of code where it simplifies things. It is ugly and crude, but extremely easy. The ability to get something in front of the customer quickly is tremendously useful for getting feedback.

Once the demo hits a database, I throw PHP away and switch to Rails. There is no reason you could not use a PHP framework instead, but at this point you begin to need the clean organization that a (decent) framework provides.

I only have one substantial application running on PHP, and I lost a lot of time re-inventing the wheel. However, I'm glad I did it. It was a great learning experience for me. With most frameworks, you are protected from the little details. With straight PHP, you can feel the bones of the web underneath. I made a number of mistakes in my design, but I'm a hell of a lot better web developer now as a result of having made those mistakes. Building a decent-sized website without the benefit of a framework is something that every web developer should do once.

Conclusion
So should you learn Ruby, if you don't already? That is up to you. If you are interested in Rails, or if you would like a language with strong regex support (and you don't already know Perl), you should think seriously about it. Don't be turned off by the backlash -- it comes from success.

1 comment:

Wolf said...

Regular expression is really wonderful to parsing HTML or matching pattern. I use this a lot when i code. Actually when I learn any new langauge, first of all I first try whether it supports regex or not. I feel ezee when I found that.

http://icfun.blogspot.com/2008/04/ruby-regular-expression-handling.html

Here is about ruby regex. This was posted by me when I first learn ruby regex. So it will be helpfull for New coders.