12 Reasons Ruby Should be Banished to Whatever Firey Pit It Came From
04-07-11
- Implicit Returns – Can you say “What the !@#$%”? This is just wrong on SOOOO many levels. This appears to be one of the many casualties of the never ending quest to eliminate commonly typed characters from the language.
- Return isn’t allowed inside a loop – This just makes exactly no sense. I suspect it has something to do with internal stack implementation, and the impossibility of making it coexist with the absurd “do” blocks that ruby lets you include after a function as a parameter. That said, I don’t care why it isn’t allowed, disallowing it is unacceptable. The only way to work around it is to pollute your code with failure indicators and spam some if failed blocks after all your loops.
- Implicit Function Calls – If I see a line of code that says “foo.bar”, I read “the bar member of the foo object”. Cool beans. What if bar is a function? No problem, this is a reference to that function, and won’t actually get called unless I add parentheses. Nope. Ruby will call that sucker whether you include parentheses or not. This is an “implicit” function call, and it heralds from shell scripting languages. It is a terrible terrible thing, and has no business in any language that is intended for use in any sizable development project. Why is it bad? Because it becomes impossible to distinguish values from function calls without tracing the code. Why should you care? Because they behave differently. A value is non-volatile (excluding threading considerations), accessing a value generates no side effects, and values require no computation (which means they are fast.) Functions, on the other hand, rarely exhibit these qualities, and sometimes exhibit none of them. Consider rand. Rand is volatile (it will return different values each time), it generates side effects (most random number algorithms will manipulate a global seed as part of the computation), and rand can be computationally intense (depending on the algorithm). Still not seeing it? Imagine you have a line of code like this: foo.edge.do_something. You realize that you also need to do another thing in the same place, so you write: foo.edge.do_something_else. Immediatly, the script breaks. After hours of debugging, you discover that some nitwit implemented edge as a function that iterates through foo’s edge list (I.E. edge returns a new edge each time you use it). Yes, this was a bad design, but ruby encouraged it, and then when it failed, Ruby hid the problem.
- Typesafety Identity Crisis – A language should either be typesafe, or not. I’m a huge fan of type safety, but I do understand why this is sometimes less than ideal for interpreted languages. That said, be all in, or all out. Languages that are NOT typesafe need appropriate implicit conversions where it makes sense. Ruby seems to error out with every minor type error, rather than gracefully attempting to figure it out, but then it lets any variable hold any value, and has absolutely no type based declarations.
- Counter-intuitive Implicit Boolean Conversions – This is basically a subset of the typesafety issue, but it’s such a pain, that it certainly deserves a specific mention. It turns out that “if arr.length” and “if arr.length > 0” behave differently. The first one will express as true when arr is a zero length array. As far as I’m concerned, 0, undefined, nil, “”, and any other essentially zero value should always express as false, especially in a typeless scripting language.
- Implicit end of line – There are two types of languages in the world: those where the end of a physical line has some operational significance, and those where it does not. In C++, PHP, Java, etc. the end of a line of code must be explicit. Ruby took the other route, and honestly, I see no reason for it. This reminds me of the “space as an operator” stupidity in CSS. Requiring an explicit end on each line clearly documents intent, and more importantly, it allows the programmer to feel comfortable wrapping long or complex code across multiple physical lines. Without this, you end up with long convoluted lines of code that are difficult to read or comment on. Additionally, sometimes logic is expressed most cleanly by placing multiple statements on a single physical line, but ruby cripples this possibility too.
- =begin, =end – OK, I can understand (sort of ) using # for comments. Shell scripts use #, Ruby is usually run as a shell script, fine. But =begin and =end for multiline comments? For real? Ruby just beat HTML/XML out of the #1 spot for most ridiculously obscure and complicated comment syntax. Someone should be proud.
- end – Exactly why do they think this is better than curly braces (I.E. {…})? Braces allow scope lines to LOOK like scope lines, and code lines to look like code lines. Having an “end” keyword just pollutes my scope lines with words, making them that much harder to distinguish from code lines. Sure, it’s easy to read, but I have to read it. The biggest mystery to me though, is why they would do this, when seemingly no compromise was too great, in the quest to eliminate a few characters from common commands.
- {…} – Let’s at least be consistent. I can’t use curly braces for if statements or function definitions, but I can use them for loops and for any function that includes a block parameter? Exactly why?
- |key,value| vs. |key_value_pair_array| vs. |value,idx| vs. |value| – Oh where to start… First off, this syntax for loops is a nightmare to type. Second, how about some consistency in how things loop? Array.each will give you a series of values, and one might think that Object.each would do the same. It doesn’t. It returns an array of key value pairs. That means that if you decide to swap an array for an object (not an uncommon change) all your loops will break, forcing you to fix them by hand. In addition, Object.each returns the key first, then the value. Array.each_with_index returns the value first, then the index (which is basically the key for the array). Last of all, why do we need an “each_with_index”? Why can’t “each” handle both cases?
- Neither ++ nor – – You would think that with Ruby’s extreme “less code” mentality, they would have increment and decrement operators. Nope. Instead they want you to use +=1, once again demonstrating their contempt for the conventions of every other major language.
- Last, but certainly not least: No native sanitization – Ruby will gladly let you write something like this: `mkdir /var/www/localhost/htdocs/#{username}`. That looks neat…until some wise guy tries to tell you that his name is “
| rm -rf /“. Then, when you create his directory, you will also delete the entire contents of your server. If ruby had any self respect, it would include the tools to prevent this sort of insanity. It doesn’t. You have to get a 3rd party gem. As a result, almost all 3rd party code of any sort is riddled with problems like this, making Ruby generally unsafe to use in connection with any inputs that you don’t have 100% control over.
At the end of the day, Ruby feels more like a shell scripting language than a legitimate language for major development. That’s probably because it is a shell scripting language, unsuitable for major development. Many of the syntactical decisions are straight from bash. It tries to fool you with some inclusion syntax and classes, but make no mistake, Ruby is for small stuff. This is not the kind of language you want to be entrusting half a million lines of code to. If you need a little more out of your shell scripting language, Ruby could be a life saver, but if you even suggest using it for a large project, your butt should be fired faster than a redneck on a Donald Trump show.

Awww. I was expecting something serious, like continued use of Ruby will cause the earth to split in half or something like that. :)