In early 2006 I had just started my career in IBM. I was the “Ruby Guy”[1] (or alternatively, the “Rails Guy”).
During a meeting with a few high-profile engineers, I presented what Ruby brought to the table. An IBM Distinguished Engineer[2] stopped me in my tracks and said, “It sounds slow”.
I love Ruby as much as a programmer can possibly love a programming language, but that engineer’s conjecture was right on the money. Ruby’s emphasis has always been on programmer efficiency, not execution efficiency.
Generally speaking, Ruby programs are significantly slower than equivalent programs in C or Java.
A lot of work has been done to improve Ruby’s performance, with a good degree of success, and that’s terrific – but is it enough in today’s world?
In many ways, yes. You’re not going to employ Ruby to calculate 13 trillion digits of Pi, nor will you use it to power the backend of a messaging app with millions of users.
However, Ruby will suit most scripts just fine. Further, I would argue that Rails still gives you the best bang for your buck in terms of web frameworks, when it comes to a large subset of CRUD-based web applications.
Ruby is lovely and has many uses, however, what Ruby is not, is the language that will define the next ten years. As beautifully designed as it is, it simply isn’t the ideal language to tackle the challenges that an increasingly distributed world throws at us.
Concurrency is the name of the game, and Ruby is, for the most part, limited in its ability to cope with it (despite valuable efforts). It’s not that you can’t do concurrency in Ruby, it’s that there are much better, battle-tested tools to do so.
If you are a fellow Ruby developer who would like to remain relevant in the next decade, I highly suggest that you start looking for something new to pair to Ruby as your main language. (Though, fair warning, you might end up replacing Ruby with it.)
Your main language for the next ten years will be highly dependent on the development context, of course. If you develop iOS apps, Swift is such a language. Android apps? Kotlin is looking good and might have a shot at that. Data Science? Julia, if they can sort out a few performance issues, could get the edge over Python and R. System programming? Rust and Go will be worth a close look, too.[3]
I’m enough of a generalist to dabble in many programming domains, but above all, I’m a web developer, so my main language for the next decade will have to excel in distributed environments where n machines make m requests, for large values of n and m (e.g., IoT alone enables this scenario).
So what comes after Ruby? Some people might argue that it’s Node.js. Not for me personally, though. I’m afraid Ruby has spoiled me. I find Ruby to be a joy to use. JavaScript, not so much.
We are looking for a high-level language that can handle concurrency like a champ, has an elegant, highly readable syntax, provides a great user experience for the developer, and… is functional. In short, fun and functional. 🙂
I find functional programming (with immutable data types) to be a significantly better approach to thinking about most problems, and modeling solutions for them, than Object Oriented programming.[4] I blame my past dabbling with Haskell and Clojure for this.
Speaking of Clojure, on the JVM, both Scala (w/ Akka), and Clojure (w/ STM & Pulsar) are valid options.
Of the two, Clojure is the one that comes closer to a great fit for me. Very close. Unfortunately, I’m somewhat of an aesthete, and coming from Ruby, the Lisp syntax still feels like a downgrade.[5]
Further, the JVM is great, but when it comes to dependable concurrency, you really can’t beat what the Erlang VM (i.e., BEAM) has to offer (ask the team at Whatsapp).
The problem with Erlang is that its Prolog-like syntax feels obsolete. I have never seen an Erlang program and said to myself, “Wow, that was a joy to read”. Or refactor. It’s not the worst, but I personally find it to be a fairly uninspiring language to work with.
Thankfully Erlang is not the only language for its highly fault-tolerant and concurrent VM. There is indeed a language worth getting excited about.
For me, that language is Elixir. Elixir fits all the requirements above and feels like a joy to both read and use.
Like many other Rubyists, when I first found Elixir I thought of it as Ruby for the Erlang VM, due to its largely familiar syntax. But it turns out to be so much more than that. In fact, it’s much more than Erlang as well.
To hastily summarize, we get:
- A highly readable, elegant, concurrent, functional programming language.
- The fantastic Erlang VM (i.e., BEAM) and OTP integration.
- Shared nothing Actor-based concurrency.
- Metaprogramming via macros.
- Polymorphism via protocols.
- A whole host of other nice features (pipeline operator, pattern matching, docstrings, streams, mix, etc).
- An excellent web framework called Phoenix.
- A fast growing supportive community, that it’s reminiscent of Ruby during the early days of Rails.
Ruby’s usage skyrocketed in the past decade and I would argue that Elixir, though not widely adopted as of yet, is well equipped to do the same in the coming ten years.
Give it a try and let me know how you like it.
- Though Sam was both literally and figuratively a Ruby guy. 😉 ^
- Now an IBM Fellow, which is the highest honor a tech person at IBM can achieve. It’s worth noting that I had not mentioned performance at all until that point. He simply figured it out based on the features of the language. ^
- Some might like Nim, instead. Crystal, with its Ruby-like syntax, is probably the most interesting option for Rubyists, despite being at very early stages of development. ^
- I suspect that the next decade, outside of system programming, will belong to functional languages (or hybrid languages heavily influenced by functional programming). ^
- I know, I know, I’m putting a lot of emphasis on syntax. That’s because it matters more than most people give it credit for. ^
Get more stuff like this
Subscribe to my mailing list to receive similar updates about programming.
Thank you for subscribing. Please check your email to confirm your subscription.
Something went wrong.
Very nice article, and I agree with you on pretty much all of it. I’m curious to read your thoughts, if any, on Crystal (http://crystal-lang.org) language.
Crystal looks very promising to me. I’m impressed by how much they accomplished so quickly and with so little support. I tweeted about it just a few days ago: https://twitter.com/acangiano/status/741082140046135296 Much like I state there, I think that Crystal + Elixir could make for a powerful, flexible combo. And for Rubyists, it will be a no-brainer. We just have to see Crystal mature enough.
“You’re not going to employee Ruby” -> “You’re not going to employ Ruby”
Good catch. Fixed.
After spending a fair amount of time with both Erlang and Elixir and co-running the Portland Elixir meetup w/ an Erlang expert. I have grown to appreciate a few aspects of Erlang’s syntax that hadn’t occurred to me before.
For instance, when scanning Erlang code, you immediately know that anything that is lowercase is static: it’s an atom, a function, a module. You don’t have to worry about it. Whereas anything that is capitalized is a variable. It doesn’t sound like much, but when we were trying to add functionality to an existing Erlang library, it was extremely valuable.
I still really like working in Elixir, but I’m also aware of the strengths Erlang has over it.
¯\_(?)_/¯
I feel like Python would minimize the sum of programmer unhappiness if every developer was forced to use one language.
So for me, Python is (still) the language for the next 10 years. Although I’m trying like the dickens to learn Haskell just to expand (explode?) my brain.
The only thing missing for me in Elixir is arrays/vectors for which you have to fall back on Erlang syntax and functions. When I raised this issue in the community the response was a defensive “What do you need them for? I’ve never needed them”. That attitude is a deal-breaker for me.
You really don’t need them. Erlang has lists where other languages have arrays because the latter are unbelievably useless in a language where your primary means of retrieving data is pattern matching.
In addition to this, arrays encourage a lot of imperative approaches which make life very difficult for you on the BEAM, which is already a huge problem for people coming into that ecosystem from Ruby.
The Erlang/BEAM virtual machine has some nice qualities, but it’s slow. It is (unless it’s been drastically redesigned since 2011) a pure interpreter that doesn’t employ JIT or AOT translation — it’s at the same level as the earliest JVM from 1995.
I spent much of 2011 porting CouchDB to iOS, and then trying in vain to get it to run at acceptable speed on an iPhone, before giving up. (It took 5 seconds just to initialize; a deal breaker for mobile apps.) Others at Couchbase (Dustin Sallings, Damien Katz) tried to get CouchDB’s storage engine to keep up with memcached, and ended up rewriting the engine in C, which is what’s in Couchbase Server.
I suspect people think Erlang is fast because it’s so parallelizable — just throw more cores or more CPUs at problems. But not every problem can be defeated that way, either because the algorithms aren’t parallel or because you’re restricted to hardware with a limited number of cores (and memory bus bandwidth.)
Thank you for your insightful comment, Jens. I entirely agree that Erlang is not the right tool for every problem.
There are much better solutions for, say, number crunching. However, I believe that for the use case I specify in the article (distributed systems, web programming), Erlang-based solutions are a very solid option.
You didn’t mention LFE (Lisp Flavored Erlang). It’s written by Robert Virding one of Erlang’s creators, and it has real macros 😉
I like Elixr, and Jens is right, unless you are taking advantage of the BEAM/OTP, it is slow. Elixir is certainly Rubyesque, but the tooling is great too.
I am keeping a sideways eye on Pony lang. It’s actor-based, OO, but supposed to be real fast, and doesn’t use a poison pill to kill all actors.
We’ve had the same issue with elixir / erlang. It’s great in terms of syntax (especially if you come from ruby) and it’s great for messaging – but it’s not great for general computing. And it’s especially not suited for background long-running processing tasks.
I love the language and wanted to adopt it at work. We needed to import some medium sized xml feeds (think 50 MB, nothing crazy).
The import script written in elixir was using parallel processing and it was pretty good – better than single threaded Go. But when we added parallel computing to Go, that killed it.
We ended up adopting Go though I don’t like it. Personally I’ve “adopted” Julia which seems to be promising for both data crunching, general computing (long running background tasks) and parallel computing.
Thanks for sharing, Adrian.
I entirely agree with you. For heavy processing, I think it’s worth keeping an eye on the following languages:
* Crystal
* Rust
* Julia
* Pony
* Nim
* C# or F# on .NET Core
* Scala (JVM and all)
Not even a mention of how JRuby is parallel, has far better GCs and VMs available to, or how it is often many times faster than “Ruby” (by which you only mean CRuby/MRI)? It doesn’t seem you’re presenting all the facts here.
JRuby is in use by hundreds of companies from Visa to Comcast to the BBC, running loads that CRuby could probably never scale up to. We’ve had users halve or quarter their AWS costs by moving to JRuby. And with the JRuby 9000 series, we have our own optimizing compiler and we are working with Oracle on a next gen runtime based on the Graal JIT.
Elixir is a very nice language and I’m sure it will see success… but what you present here as “Ruby” only covers one runtime: a runtime with no JIT, limited GC, and non-parallel execution. Posts like this turn people away from Ruby for the wrong reasons, reasons we are actively addressing in JRuby.
And besides…you KNOW JRuby…I’m surprised you’d completely ignore it in this post 🙂
JRuby is a worthwhile effort. Thank you for mentioning it.
Are you familiar with Paul Graham? And this essay?
http://paulgraham.com/hundred.html
It’s many years old. And it’s a bit more “meta” than your article. But the languages you describe as being “interesting” are, so frequently, cross-pollinated from multiple other languages. And that’s one of the points he makes.
To each his own. I actually like Perl and Groovy (I tend to think of Groovy as Perl for the JVM) and I enjoy Scheme implementations, if for no other reason than the sheer density of how much functionality you can implement in 100 (or 1,000) lines of code. I’ve written tools which parse hundreds of megabytes of logfiles, distill useful information from them and output them to a CSV I can open in Excel and peruse. The tool was < 300 lines of Perl (that's after you trim out all the extra whitespace and comments; as you, yourself, point out in another of your articles, sometimes that "next programmer" is you).
I don't mind the syntax of Lisp / Scheme because I recognize that all compilers / interpreters turn your source code into an Abstract Syntax Tree and Lisp is just a serialized, text-based AST; it's trivially easy to convert between the two. Once you start thinking in terms of ASTs, your mindset WRT how programming SHOULD BE completely alters. Think of it as safe, legal LSD for programmers; that kind of mind-altering, and not in a bad way. I wouldn't be surprised if the Next Programming Language is one where you create a graphical AST on your tablet, bypassing the text-based input entirely. We all know that tablets really aren't so good for text input. If you can eliminate the need to input text and convert the text to an AST before it's interpreted / compiled ….