If you organized programming languages into tiers based on their popularity, they would fall into three tiers. The top tier would include the mainstream languages such as Java, JavaScript, Python, Ruby, PHP, C#, C++, and Objective-C. While some top tier languages may be fading, you’d better know one or more of these languages if you want to easily find a job.
Second-tier languages are waiting to break into the mainstream but haven’t quite made it. They have proven their worth by building strong communities of support, but they still aren’t used by a large number of more conservative software companies. Scala, Go, Swift, Clojure, and Haskell are languages I would put in the second tier. Some companies use these languages in a few services, but wide industry use is rare (except for Swift, which is starting to overtake Objective-C as the primary iOS language). Go and Swift both have a good chance of moving from the second tier to the first over the next two to three years.
Most of the languages in the top tier are firmly entrenched. It takes a while for a programming language to fall out of the top tier, and it’s very hard for a second-tier language to break into the top tier.
The emerging languages of this article are in a third tier, and they are just starting to gain a following. Some languages have been in the third tier for many years, never taking that next step toward popularity, while others have burst onto the scene in just one or two years. Here are five languages that fall into the latter category within the third tier.
Emerging languages: Why these five?
The five programming languages that I’ll focus on are fairly new (so this might be the first time you hear about them in detail), and they clearly have a strong chance of breaking into the group of second-tier languages in the next two to three years. Maybe someday one of these languages will even be able to crack the top tier.
Here’s why these five languages were chosen for this list.
Elm is becoming popular within the JavaScript community, primarily among those who prefer functional programming, which is on the rise. Like Babel, TypeScript, and Dart, Elm transpiles to JavaScript.
Rust is a systems programming language meant to replace a lot of C and C++ development—which is why it’s surprising to see this language’s popularity growing the fastest among web developers. It makes a little more sense when you find out that the language was created at Mozilla, who is looking to give web developers that are forced to write low-level code a better option that’s more performant than PHP, Ruby, Python, or JavaScript. Rust was also crowned the “most loved” technology in StackOverflow’s 2016 developer survey(meaning it had the most users who wanted to keep using it).
Kotlin has been around for about five years, but it finally reached the production-ready version 1.0 this year. Although it hasn’t achieved the popularity of Scala, Groovy, or Clojure—the three most popular and mature (non-Java) JVM langauges—it has separated itself from the myriad other JVM languages and seems poised to take its place among the leaders of this group. It originated at JetBrains—makers of the popular IntelliJ IDEA IDE. So you know it was crafted with developer productivity in mind. Another major reason Kotlin has a bright future—you can easily build Android apps with it.
Crystal is another language that hopes to bring C-like performance into the highly abstracted world of web developers. Crystal is aimed at the Ruby community, with a syntax that is similar to and, at times, identical to Ruby’s. As the already large number of Ruby-based startups continues to grow, Crystal could play a key role in helping take those applications’ performance to the next level.
Elixir also takes a lot of inspiration from the Ruby ecosystem, but instead of trying to bring C-like benefits, it’s focused on creating high-availability, low-latency systems—something Rails has had trouble with, according to critics. Elixir achieves these performance boosts by running on the Erlang VM, which has a strong performance reputation built over its 25 years in the telecom industry. The Phoenix application framework for Elixir—more than any piece of this blooming ecosystem—has given this language legs.
Now, take a quick peek at four of these five languages making their way up the popularity ladder, according to StackOverflow and GitHub data:
Each of these languages already has an enthusiastic community and its own weekly newsletter (That’s when you know you’ve made it!). If you’re thinking of learning a younger language with exciting possibilities for the future, read these elevator pitches for each of the five languages I just mentioned—written by experienced enthusiasts and leaders in their respective ecosystems.
Elm
Elm is a usability-focused functional programming language that compiles to high-performance JavaScript. You can use it with or without JavaScript to build user interfaces on the web. Elm’s primary benefits compared to JavaScript are reliability, maintainability, and programmer delight. More specifically:
-
No runtime exceptions: Production Elm code has a reputation for never throwing runtime exceptions. A far cry from “undefined is not a function.”
-
Legendarily helpful compiler: Elm’s compiler is widely praised for having the most helpful error messages in the business. “If it compiles, it typically just works,” is a common sentiment, even after a serious refactor. This makes large Elm code bases much nicer to maintain than large JS ones.
-
Semantic versioning automatically enforced: elm-package enforces semantic versioning automatically. If a package author tries to make a breaking API change without bumping the major version number, elm-package will detect this and refuse to publish it. No other known package manager enforces semantic versioning this reliably.
-
Fast and functional: Elm is a pure functional programming language, which guarantees no mutations or side effects. Not only do these guarantees make Elm code scale nicely, but they also help it render application UIs faster than React, Angular, or Ember.
-
Powerful tooling: elm-format formats source code according to a community standard. No more arguing over style conventions. Just hit Save in your editor of choice and your code becomes beautiful. elm-test ships with batteries-included support for both unit testing and fuzz testing. elm-css lets you write Elm code that compiles to a .css file, so you can share code between application and stylesheets to guarantee your constants never get out of sync.
Elm code can also interoperate with JavaScript, meaning you can introduce it in small doses to your JS code base so that you can still leverage the enormous JS ecosystem and avoid reinventing the wheel.
Check out guide.elm-lang.org to get started, Elm in Action for elaboration, and How to Use Elm at Work if you’re wondering what it would be like to use Elm at your job.
Rust
Rust is a systems programming language that combines C-like efficiency and control over memory with functional language features such as strong static typing and type inference. It has three primary design goals:
-
Safety: Many C-like languages open the door to memory errors resulting from manual memory management (e.g., dangling pointers or double-frees). Rust takes best practices from modern C++ such as RAII and smart pointersand makes them language requirements, systematically ensuring that pure Rust code is memory-safe.
-
Speed: Nearly all languages run slower than C because they provide abstractions that make software development easier but with substantial runtime overhead (e.g., garbage collection and dynamic dispatch). Rust focuses on “zero-cost abstractions,” or methods of making programming easier that don’t cost anything at runtime. For example, Rust manages memory at compile time and uses static dispatch for generics (similar to C++ templates, but more type-safe).
-
Concurrency: Concurrent code in systems languages is often fragile and error-prone, given the tricky nature of programming with threads. Rust tries to alleviate these issues by providing type-level guarantees for what kinds of values can be shared between threads and where.
Rust also has several distinguishing features:
-
The borrow checker: Rust’s famed feature is a static analysis tool that reads your code and stops compilation if it could cause a memory error. This works by institutionalizing the notion of values being either owned by one place or borrowed by many places and subsequently analyzing how ownership of a value changes over the lifetime of the program. The borrow checker also precludes data races in concurrent code using the same set of rules.
-
Composition over inheritance: Instead of using an inheritance-based class system such as C++ or Java, Rust uses traits, or composable interfaces, to support modular programming. Rather than specifying that a particular type is part of a class hierarchy, a programmer can describe a type by its capabilities, e.g., saying that a type should be Printable and Hashable instead of inheriting from a PrintableHashable class.
-
Fabulous tooling: Any C/C++ veteran knows the pain of installing dependencies, compiling code on multiple platforms, and battling arcane CMake configurations. Rust saves the endless hours spent yelling at GCC by providing a sane package manager and cross-platform-compatible APIs.
For more info, check out The Rust Book and Rust by Example.
Kotlin
Kotlin is a statically typed language that targets the JVM and JavaScript. Kotlin was born out of need at JetBrains, which was looking for a new language in which to write its tooling, which was mostly written in Java. Something that would allow it to leverage its existing codebase and at the same time resolve some of the issues it had with Java. And it was precisely common pitfalls that one encounters when writing software that shaped much of Kotlin’s characteristics.
-
Conciseness: Reduce the amount of boilerplate code necessary to express certain constructs.
-
Versatile: Create a language that is suitable for any type of industrial application development, be it web, mobile, desktop, or server-side.
-
Safe: Let the language handle some of the common pitfalls made with issues such as null reference exceptions.
-
Interoperable: Permit the language to interoperate with existing Java codebases, libraries, and frameworks, allowing for gradual adoption and leveraging existing investments
-
Tool-enabled: JetBrains makes tools and it does so out of the belief that many mundane tasks can be automated and lead to more efficient and productive development. As such, the language has to easily allow for tooling.
Kotlin has and will always be about pragmatism—seeing common issues we encounter frequently when writing code and trying to help address these. This surfaces through various language features such as:
-
Null-safe by default: Kotlin types by default are not nullable, avoiding pesky null reference or pointer exceptions.
-
First-class delegation: The ability to delegate functionality of a class member to an external function, thus allowing for reuse and better composition.
-
Conventions: A series of conventions that allow for writing expressive code, giving way to creating a strongly typed domain-specific language that provides better discoverability and easier refactoring. Kotlin 1.0 was released in February 2016 after more than five years in development and extensive testing in real-world projects. Currently, over ten products at JetBrains use Kotlin, as do companies such as Amex, NBC Digital, Expedia, and Gradle.
For more information, visit kotlinlang.org
Crystal
Crystal is a general-purpose programming language with the motto “Fast as C, slick as Ruby.”
It’s a high-level, statically typed, compiled, fully object-oriented programming language with advanced type inference and garbage collection.
The design goals of Crystal are:
-
Have a syntax similar to Ruby (but compatibility with it is not a goal).
-
Be statically type-checked but without having to specify the type of variables or method arguments.
-
Be able to call C code by writing bindings to it in Crystal.
-
Have compile-time evaluation and generation of code, to avoid boilerplate code.
-
Compile to efficient native code.
Crystal has unique features such as:
-
Channels: Crystal uses Channels inspired by CSP (just like Go) to achieve concurrency. It has cooperative and lightweight threads called Fibers to achieve this. One can easily create a Fiber with the spawn keyword and make the operation asynchronous/nonblocking.
-
Macros: Crystal uses macros to avoid boilerplate code and gain metaprogramming abilities. Macros are really powerful and evaluated at compile time, meaning they have no performance penalty.
-
crystal command: The crystal command itself is really powerful and comes with great built-in tools. It is used for creating a new project, compiling, running the test suite, and much more. There’s also a built-in code formatter that you can use with crystal tool format. There’s also crystal play, which is an interactive playground for some quick prototyping, just like irb.
Bonus:
Expressiveness: Code is read much more than it is written. Thanks to Ruby, Crystal is really expressive and easy to understand. It’s easy for newcomers to learn and pays off in the long run with less maintenance/noise.
For more information, you can check the official Crystal Book and Crystal for Rubyists.
Elixir
First introduced in 2012, Elixir is a general-purpose functional language designed for productivity, scalability, and maintainability. While the language is relatively new, it compiles to bytecode that runs on the Erlang Virtual Machine (BEAM). The Erlang VM was born out of the telecom industry, has been evolving for almost 25 years, and powers many massive, high-availability, and low-latency systems.
Currently, Elixir is primarily used to build web applications using either Cowboy, which is a bare-bones HTTP server, or Phoenix, a full-featured web application framework. It is also building steam in the embedded hardware space with the Nerves framework.
The Elixir syntax and toolchain both draw some inspiration from Ruby. While the syntax similarities are only skin-deep, the toolchain will feel familiar to anyone who knows Ruby. The commands are well thought out, are easy to use, and facilitate great developer productivity.
Language goals
- “Friendly” functional programming: The power and benefits of a functional language, with a clear and approachable syntax.
- Highly concurrent and scalable: The language shouldn’t get in the way of tackling big problems for many users.
- Excellent development tools: For building, managing dependencies, testing, and deployment.
Distinguishing features
- Immutable data structures and no side effects help to make large systems maintainable and easier to reason about.
- Supervision allows you to define an internal process tree and set rules for automatic error recovery.
- Pattern matching provides an alternative to conditionals and guard clauses.
- Actor-based, share-nothing concurrency with processes is a good fit for solving today’s concurrency issues at scale. See The Road to 2 Million Connections.
- Very efficient resource management means you can serve many users with limited hardware. See Why WhatsApp Only Needs 50 Engineers for Its 900M Users.
- Hot-swappable code for zero-downtime deploys.
Elixir and Phoenix are growing in popularity because the combination makes it easy to build sophisticated, robust web APIs and applications with great maintainability, excellent performance, and scalability. That’s why Pinterest, Bleacher Reports, and many other companies have invested in Elixir for key parts of their product infrastructure. You can have productivity without sacrificing performance (or vice versa), a claim not easily made by many other languages.