Monday, September 03, 2007

Ruby Matters: A Place to Put Your Stuff

Why are so many people into Ruby? I get this question a lot because I speak at a lot of Java conferences and talk about Ruby and JRuby. In this and several more blog entries, I'm going to explore this question in depth.

For myself and many of my peers, it was a rite of passage to learn all the intricate tricky stuff in C++. Once I got over my fascination with C++ and got tired of banging my head against all of the arcane nonsense in the language (I used to know the details of all the different ways you could use the word const, but I've fortunately purged that knowledge), I asked one of my colleagues why he continued to love it so much. "Knowing C++ makes me part of the C++ priesthood. When people ask me questions, I'm purposely cagey when I give them answers because I think they should work as hard as I did to figure this stuff out. I don't want to give my advantage away." I shuddered and was glad I wandered to greener pastures.

After a brief visit to the refugee camp of Delphi, I made it to Java and thought I was in heaven. Finally, a language that made some sense. I liked the locked down nature of the language because I thought that Java helped prevent mistakes, especially for large projects. This is before I had embraced unit testing, so that seemed like a good thing. I would gladly give up flexibility for perceived safety. This was when I used to think that one of the most important duties of a computer language was to prevent mistakes first and support building interesting stuff second. Interesting stuff must be hazardous to large projects, and I was an Enterprise Developer. After more than a decade in Java, I started playing with Ruby because I'm a bit of a language geek and I was taking the advice in The Pragmatic Programer to learn a new language every year. But, at the time, Ruby was just a cool little scripting language with nice syntax.

When Ruby on Rails came out, I started looking at it with great interest because it was so vastly different from the Java frameworks with which I was so familiar (this was just after I had written a book comparing them). And the more I looked at Ruby, the more puzzled I got. Wow, there's some funky stuff in there, and I couldn't understand what some of the code meant. So, I dug deeper. And slowly, I gained enlightenment. At first, I thought that it was just more of the same "obfuscated code" syndrome from C++. But I later understood that it wasn't.

The epiphany really came when I understood what some of the Rails code was doing with meta-programming, which made me look closer at the core Ruby stuff. Meta-programming was supposed to be scary stuff that only wild hackers did. But it made problems melt away, in very few lines of code. If you look at how attr_accessor works, it's so simple. I thought for a long time that attr_accessor was a keyword or something infra-structural that I shouldn't bother looking at (before I realized that lots of stuff in Ruby looks like keywords but they aren't).

I have come to understand that meta-programability is an extremely important part of a language. So many things that we solve in languages like Java with complex structures and hierarchies are much more elegantly solved with meta-programming. This realization led me to start looking around at other languages, like Smalltalk and Python.

That's when it hit me: one of the things that makes Ruby so powerful is that it already gives you a place to put your stuff. If you don't think this is any different than Java, check out whytheluckystiff's Seeing Meta-classes Clearly article. I'll wait... Yes, there is a shadow meta-class behind every object in Ruby, giving you the syntax and location to put much of the interesting meta-programming stuff in Ruby. You can do lots of the same meta stuff in, for example, Groovy, but you have to create a Groovy builder object to do the equivalent of eval. And, doing class_eval would take more building a place to put it. I was talking to a Python programmer recently, talking about the same subject, and I got the same response: "Yeah, Python can handle that, but you'll have to build a place to put it." One of the elegant features of Ruby is that it comes pre-defined with places to put your important stuff, rather than forcing you to build a place to put your stuff. Which is why Paul Graham says that Lisp is the most powerful language available; because you are writing code in the abstract syntax tree, you are living in the place where stuff gets put.

In the next post, I'll talk about the special case of Smalltalk, tools, and code generation vs. synthesis.


Robert Stehwien said...

Your path through languages is somewhat similar to my own. I began with C moved to C++, then Java, and now I'm interested in Ruby, Smalltalk, Lisp and Erlang.

Sadly I had to return to C++ after Java and I felt so constrained once more. I even remember most of the secrets of const.

Luckily I'm sneaking out the back to visit C# and ActionScript professionally while messing around with Ruby and Squeak on the side.

I'm looking forward to the rest of your articles.

Debasish said...

C++ priesthood .. Huh! I like the term .. truly some of the template metaprogramming tricks in C++ are nothing short of black magic.

reviewer dude said...

What is an example of something that you can't do in Python because there is "no place to put your stuff"? Python objects also have classes and metaclasses.

Maxim Khailo said...

C++0x will allow easier meta-programming constructs. I have written some of my best apis in C++. C++ has a well defined syntax and was designed so that you can create your own custom types to act as natural as built in types within this syntax. The black magic comes about when people try to do things outside the syntax.

That is where dynamic languages shine in the context of meta-programming...they allow for more natural syntax..DSL if you will. Lua comes to my mind.

However, ironically the best language to create DSLs that I have found is Haskell. Primarily because of the power of creating your own monads and the ability to define your own operators completely.

cleve said...

I enjoyed your talks on Ruby and JRuby at NFJS (i'm no longer stalking you :-)). Now I am learning Ruby the language and finding it a joy to solve problems that would have taken me down some very dark alleys in Java/C#/C++.

My langugage path is similar to yours C=>C++/Smalltalk=>Java/C#, with some wobbles on the way Objective C, Eiffel and Modula-2.

As I start to GET this meta programming lark, I'm wondering why it isn't mainstream. Sadly, adequate support for it in mainstream languages has been severely lacking. I think Ruby/JRuby, Groovy and Microsoft's DLR will at last bring meta programming to the masses.

Whether we can handle it is another matter...