16 December 2009
What is wrong with Ruby
After using Ruby massively for a few years, I think I have now enough understanding to finally see its main flaw. As a starting point to try to see it too, consider mentally splitting the Ruby language into two parts - “programming part” and “metaprogramming part”. This is of course a fully artificial distinction, as in reality they are closely tangled together, but I find such an attempt a useful experiment.
What I would consider a part of Ruby’s normal programming features are the things programmers who ship end-user applications use everyday - classes, objects, methods, loops, variables etc. The metaprogramming features are what is mostly used by people who build applications for other programmers, but normally not by the “average Joe”, so the techniques behind things like Rails, RSpec, Rake, Rack and other major Ruby frameworks and libraries. Much of the appeal of those projects lies in the elegance of the languages they make available to their users, making it easy to describe solutions to problems the given framework is targeting. The specific features I have in mind are things like metaclasses, instance_eval, class_eval, method_missing, alias_method an so on, all hidden behind an easy to use abstraction layer.
The big success of Ruby was that it enabled things like Rails to happen at all. They were languages before that could make frameworks of this kind possible, like Common Lisp or Smalltalk, but they never became mainstream and nothing similar in popularity and impact to Rails never was built around them. Ruby had some of the same capabilities of Lisp or Smalltalk, while being more accessible to the average Joe (or to the not-so-average David). It is interesting to consider how much syntax Ruby has - I am not strongly conviced about this myself, but after reading parts of Chomsky’s “On Language” it occurred to me that maybe the more syntax a programming language has, the better it maps to the parts of our brains shaped by the syntax-rich natural languages. This would perhaps explain why Lisp or Smalltalk with their minimal syntax didn’t gain that much popularity despite their huge advantages. Instead they ended up being used mostly by people that have their brains already trained at thinking about things in different ways then just with natural language, for example people well versed in mathematics or physics, or specifically trained in programming with them for a prolonged period of time.
The problem I see is that the superiority of Ruby in the domain of creating programming frameworks or DSLs happened to a great extent accidentally. Ruby was not designed with things like Rails in mind and it is clearly visible now. The metaprogramming features are very specific and very chaotic, they do not form a coherent set of generic tools, the way the “programming part” of Ruby is a coherent set of generic tools for describing computations. People building advanced libraries like Rails have to use those features in ways they were not meant for.
You can see my metaprogramming presentation for advanced examples of various Ruby oddities in this area, one simple example is the situation where you want to augument an existing method with some code around it. The way you do it in Ruby is by aliasing methods - the language feature you use has no relation to your intent. This is how it looks like:
def wrapped_method puts "2 + 2 = 4" end puts "Before augumentation" wrapped_method puts alias :old_wrapped_method :wrapped_method def wrapped_method puts "1 + 1 = 2" old_wrapped_method puts "3 + 3 = 6" end puts "After augumentation" wrapped_method
The lack of an adequate programming “metalanguage” is what I consider the biggest flaw of Ruby, but also the most promising direction of programming languages development. It is good to look at some other languages and compare them in this respect. For example JavaScript can achieve some of the same metaprogramming capabilities of Ruby with much less language constructs - objects as hash-maps, first order functions, the ability to changes the context of a function etc. are all aplicable to a wide variety of problems without having the narrow nature of the Ruby techniques used to achieve the same effects. Alan Kay has some very interesting things to say about this, so if you are interested in those topics, you may start with listening what he has to say.
Comments ():
hosiawak, 23 December 2009, 4:03 pm
I guess I get your point about impedance mismatch in Ruby between the regular OO stuff and the metaprogramming stuff, but I think from a pragmatic point of view the fact that metaprogramming (even though it may not be nice) is possible at all is more important than the fact that it’s not nice (or pure or whatever you want to call it). Especially for a “glue”, get-stuff-done language like Ruby.
For example, I also would like to see Sequel’s DSL be implemented by using macros and not by having to hack Symbol and other core classes. But does it really matter for the Sequel library user ?
Nice article. You should write more (said the guy who doesn’t write at all) :)