Like natural languages, learning a new programming language and mastering the frameworks built on top of it allows you to think differently about how to think—in the case of developers, changing how you think about problems you’ve already solved, and affecting how you think about problems in the future. For me, these alternative perspectives sometimes give new insights into the problem itself, and tend to change the way I think about solving problems of that nature. I’d like to think it’s for the better.
The language I’ve been privileged to learn for the past year is Ruby, so aptly named as it is indeed a gem of a language. Given my relatively brief exposure, if I had to describe the language it would be an “object-oriented functional-influenced reflective programming language”, though I’m sure the masters would have plenty more to add. Coming from a Python background, I’ve found the language pretty easy to pick up. This post attempts to summarize some of my thoughts on what makes Ruby great.
Everything is an Object
Perhaps the first concept any newcomer will learn is that in Ruby, everything
is an object. There are no primitives. Everything (yes, even integers or
booleans), descends from the
Object class. This may seem odd, as one would
imagine that allocating a whole object for each primitive is wasteful (this
doesn’t actually happen, thankfully, but it’s still initially an odd feeling).
However, once you consider that Ruby was created for programmer productivity,
this makes a lot of sense. Ruby’s “everything is an object” philosophy seems to
be the stepping stone from which the rest of the language’s design was based,
and makes the language very consistent.
Everything Returns Something
In Ruby, every statement returns something. Whereas other languages usually
require some sort of explicit
return statement or temporary variable to hold
a value so it can be read later, Ruby allows you to be really concise
without losing readability. For example, consider a
switch statement in
Java (this is a silly example for illustrative purposes only):
In Ruby, you could write this as:
Notice how we were able to treat the entire
case block as a single expression
and assign its value to a variable. Ruby’s approach in this and other
situations like it makes for much more concise code without loss of
Ruby is Self-Aware
Alright, we’re not talking Skynet here, but Ruby boasts some features that pretty much let a program reason about and construct itself during runtime. This kind of metaprogramming is really cool. For example, there comes a time in many programs where a series of boilerplate declarations are required, whether they be constants or even similar methods following a general template. With traditional languages, one must declare each of these explicitly.
With Ruby, one can define what is called a domain-specific language (DSL), more easily than what would be possible with most other mainstream languages. For example, the testing framework RSpec allows you to write code like the following:
This is perhaps more a case for RSpec and Behaviour-Driven Development, but what’s important to notice is how this doesn’t really read like typical boilerplate test code. Instead, what we see is actual written language like “describe”, and “include”, which when read actually sounds more like a natural language than a programming language.
Under the hood, this is all powered by Ruby’s powerful ability to metaprogram itself, changing the syntax of the language to make it more useful.
Imperative and Functional
Functional programming has seen a burst of interest over the past few years. Unfortunately, it’s not the most intuitive to read, as humans naturally think imperatively, and this seems to have hindered its adoption into more mainstream use. I personally feel that while the functional paradigm is indeed a powerful one, purely functional programs don’t scale very well, and are much harder to understand. I imagine that opinion will be met with significant resistance, and I’m hopeful that I’ll be proved completely wrong one day.
For now though, Ruby provides an excellent blend of functional and imperative language features. One major difference I like to tote between Ruby and Haskell (a functional programming language) is that it reads much more naturally while still allowing composition of functions. Consider the following problem: how do you reverse a string of words?
With the Haskell version, you had to read the code from right to left, and furthermore had to almost create a parse tree in your head in order to fully understand what was going on. With Ruby, you simple read the code from left to right as is natural, and applied each transformation until you obtained the desired result. Ruby has an almost pipeline-like interface for transforming data.
Granted, this kind of one-off comparison isn’t entirely fair, but it summarizes what I think is a general advantage of Ruby code over Haskell for everyday use.
Great for Scripting
If you’ve ever done any shell scripting, you’ve surely had frustrations with
the likes of
bash or any other shell language. Ruby provides a higher-level
programming interface for shell scripts, but keeps around a lot of the idioms
familiar to shell scripters; it’s shell scripting on steroids.
For example, if you’ve already got some shell script that does the job, but you wanted to do some additional processing on it, you can easily just integrate that code into a Ruby script by dropping it in some backticks:
While the above example isn’t particularly interesting (and somewhat abuses
backticks for sake of example), it demonstrates how easy it is to throw a quick
and dirty script together for on-the-fly scripting. Furthermore, the dollar
sign variables like
$?, etc. work the same way in Ruby, making the
transition to using Ruby over a traditional shell language that much easier.
There’s Something for Everyone
In writing this post, I know I’m a little late to the show. Ruby has been around for years, and you need look no further than the vast number of packages that have been written, or the success of the Rails web framework to see that there’s a lot Ruby has to offer. I would encourage you to check it out.