<< Go Back

Words from Jacob Herrington >>

Howdy! 🤠

I write code at Engine and I run the devpath.fm podcast. I also help maintain the Solidus platform.

Sometimes I do consulting through Narvi.

I live in Northwest Arkansas with my incredibly talented wife Kristen and our dogs.

Social Links


I'm trying to fool conferences into giving me a microphone.

  • My Heroes Are Imposters Too (200OK 2019):
    Slides | Video


I like to help organize conferences. I've been a board member, fundraiser, or talk reviewer for each of the events on this list.


I use all of these tools daily-ish.

~$ ./jh.codes

5 Powerful Programming Languages to Stretch Your Brain

August 11, 2019

Earlier this year, I had a conversation with Andy Hunt and Dave Thomas (joint authors of The Pragmatic Programmer and original signatories of the Agile Manifesto). They recommended (and have suggested in the past) the practice of learning at least one new programming language a year.

The reasoning behind this practice has very little to do with marketing oneself or even using the language. In reality, the most significant benefit of learning a new programming language is the stretching of the mind and the creation of new neural pathways that allow you to look at problems in new and unique ways.

I’ve compiled this list of languages primarily because they are languages I’m interested in spending more time learning, but also because they exemplify specific language characteristics and programming ideologies very well.

So without further ado, this is a list of languages you should learn to stretch your brain:

1. Ruby

Ruby language logo

Ruby is built for programmer happiness. That can mean different things to different people, but it’s the first programming language that I’ve come to love.

The interesting thing about Ruby is that it’s designed to embrace Object-Oriented Programming.

OOP was created by Dr. Alan Kay, who once said: “Object-oriented programming to me means only messaging, encapsulating and hiding state, and extreme late-binding of all things.” Ruby is good at this stuff.

Due to the nature of Ruby’s message-sending-obsessiveness, it’s an incredible environment to learn true OOP. I recommend Sandi Metz’s wonderful Practical Object-Oriented Design in Ruby as an introduction to Ruby’s strengths when it comes to designing objects and message sending.

Another mind-stretching feature of Ruby is arguably more divisive than OOP. Ruby embraces metaprogramming, which can be loosely defined as code that can reason about and generate other code.

Being able to manipulate programs via metaprogramming, while sometimes frustrating, can require an extreme paradigm shift in your mental model of the relationship between programmer and programming language.

# FizzBuzz in Ruby
# https://github.com/zenware/FizzBuzz/blob/master/ruby.rb

def fizz_buzz(num)
  result = ''
  result += 'Fizz' if (num % 3).zero?
  result += 'Buzz' if (num % 5).zero?
  puts result.empty? ? num : result

(1..100).each { |x| fizz_buzz x }


2. Elixir

Elixir language logo

While Elixir might look a little bit like Ruby, it’s very different. It’s a functional programming language.

Elixir is a language that embraces an idea called the Actor Model, devised by Dr. Carl Hewitt. In the Actor Model, everything is an actor.

(“Everything is an actor” sounds a lot like “everything is an object,” but I’ll leave such comparisons to academics)

Learning to think about actors is a challenging mental exercise that will lead to seeing problems in a new light.

Another mind-bending feature of Elixir is its relationship with Erlang. Elixir runs on the Erlang VM (BEAM), meaning that at some point most Elixir developers have to develop some comfort with Erlang.

I could easily run off on a tangent here, but the most interesting thing about Erlang (in my opinion) is its mind-boggling prowess when it comes to concurrency. Writing Elixir means learning to think concurrently, a skill that can be applied in a multitude of programming environments.

Finally, Elixir is a beautiful exemplar of a concept called pattern matching. Pattern matching is a very powerful functional language feature that enables you to interact with data in a very concise and safe way. Pattern matching is not exclusive to Elixir, so a solid understanding of pattern matching in your Elixir code will translate to other languages and problems easily.

# FizzBuzz in Elixir
# https://github.com/zenware/FizzBuzz/blob/master/elixir.exs

fizzbuzz = fn n ->
  cond do
    rem(n, 15)== 0 -> "FizzBuzz"
    rem(n, 3) == 0 -> "Fizz"
    rem(n, 5) == 0 -> "Buzz"
    true           -> to_string n

Enum.each 1..100, &IO.puts(fizzbuzz.(&1))


3. Rust

Rust language logo

Rust is an up-and-coming systems language. That means it’s particularly suitable for writing software when performance matters.

Rust is a fast, compiled language that brings some new ideas to the table. It is expressly intended to solve a number of the memory safety issues that arise when writing C++, which is frequently used to solve similar systems programming problems.

In Rust, you can learn about writing low-level code that interacts directly with hardware, you can learn about concurrency, you can learn about a couple of different paradigms, and you can learn it all with relative safety.

One of the most attractive things about the Rust language is that it opens a problem space customarily associated with languages infamous for their pitfalls and arcane idiosyncracies to mere mortals.

Learning Rust forces you to learn about the machine running your code without forcing you to worry about solved problems.

One other brain enlarging feature in Rust is called macros. Macros are a form of metaprogramming that enables developers to write less code and be a little less specific when it’s convenient. Not without caveats, macros are challenging to reason about and therefore can help you to develop a different perspective on the metaprogramming you’ve seen in languages like Ruby.

// FizzBuzz in Rust
// https://github.com/zenware/FizzBuzz/blob/master/rust.rs

fn fizzbuzz(i: u8) {
  if i % 15 == 0 {
  } else if i % 3 == 0 {
  } else if i % 5 == 0 {
  } else {
    println!("{}", i.to_string());

fn main() {
  for i in 1..101 {


4. TypeScript

TypeScript logo

You could make the argument that TypeScript isn’t a language; it’s a “superset” of a language. That’s fine. It’s still on my list.

For those who are unfamiliar (which would be hard considering its popularity), TypeScript is a language that compiles directly to JavaScript. It adds some additional features to the JavaScript language, but it still feels like JavaScript.

The brain stretching in TypeScript comes from the incremental approach in which it can be adopted and its focus on static typing. If like me, you come from a web background with languages like Python, Ruby, or PHP, static typing is generally a foreign concept. However, TypeScript is a friendly way to introduce yourself to this handy language feature.

Learning TypeScript will deepen your understanding of the JavaScript ecosystem, give you a strong vision of the future of JavaScript, and introduce you the benefits of static typing.

// FizzBuzz in TypeScript
// https://github.com/zenware/FizzBuzz/blob/master/typescript.ts

function fizzbuzz(num: number): string | number {
  if (num % 15 === 0) return 'FizzBuzz';
  if (num % 5 === 0) return 'Buzz';
  if (num % 3 === 0) return 'Fizz';
  return num;

for (let i: number = 1; i <= 100; i++) console.log(fizzbuzz(i));


5. Haskell

Haskell logo

Haskell is the most esoteric language on this list. It has lofty goals and ideals that make it excellent for challenging your brain.

Haskell is described as “purely functional” meaning that state is entirely immutable in this programming language. Learning to work with totally immutable state forces you to develop a wholly different approach to working with data.

Working with Haskell will result in developing some understanding of lambda calculus, which is relevant to all functional programming.

Many developers who work with Haskell also comment on the clarity of meaning and purpose experienced with reading Haskell. While this is subjective, the language itself tends to produce code that is very explicit and in many cases, obvious. No one gets upset when code is too obvious. Unironically, Haskell code tends to be very concise.

One of the most challenging concepts in Haskell is called a Monad. Monads allow developers to avoid typing excess code and string together multiple computations. The Haskell documentation frequently describes Monads as “a strategy for combining computations to produce more complex computations.”

Monads are not entirely exclusive to Haskell, but Haskell is known as being a language in which they are well implemented.

-- FizzBuzz in Haskell
-- https://github.com/zenware/FizzBuzz/blob/master/haskell.hs

module Main where

fizzbuzz :: Int -> String
fizzbuzz x
    | x `mod` 15 == 0 = "FizzBuzz"
    | x `mod` 3  == 0 = "Fizz"
    | x `mod` 5  == 0 = "Buzz"
    | otherwise       = show x

main = mapM (putStrLn . fizzbuzz) [1..100]


While programming languages are simply tools and tools should not be blamed or praised in the place of those who use them, different tools do unlock new techniques.

By introducing yourself to new tools and the techniques they enable, you can become a more well-rounded and creative engineer. If you are curious and adventurous enough, you may even find language features and programming paradigms that you can bring back to your preferred language.

I’d love to hear if this list inspires you to investigate one of these five languages, or if there is one you think I missed! 🤠