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 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
end
(1..100).each { |x| fizz_buzz x }
Resources:
2. Elixir
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
end
end
Enum.each 1..100, &IO.puts(fizzbuzz.(&1))
Resources:
3. Rust
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 {
println!("FizzBuzz");
} else if i % 3 == 0 {
println!("Fizz");
} else if i % 5 == 0 {
println!("Buzz");
} else {
println!("{}", i.to_string());
}
}
fn main() {
for i in 1..101 {
fizzbuzz(i);
}
}
Resources:
4. TypeScript
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));
Resources:
5. Haskell
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]
Resources:
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! 🤠






Oldest comments (97)
really i have many of them for first time but will go through once and all. Thank oyu
It's not important that you learn all of them, but I'd recommend learning at least one of them this year.
Try to pick one that is very different from the languages you use most frequently!
Thank you for the post. Interesting.
Sure, but if you want to solve real world tasks, just learn C and forget about the rest... meditate on that for a while, it'll help you grow.
C is a great language, but as the adage goes, if all you have is a hammer everything looks like a nail.
C is absolutely terrible for some problem spaces.
C is great if you're going to do some kernel hacking or develop drivers and stuff like that.
For web programming and mobile programming C is not the right tool for the job and its quite outdated as well since it lacks support for the main programming paradigms in use today.
Exactly ☝️
that's because the web is a poorly planned and implemented disaster.
Seems to be pretty successful to me, but I get what you mean.
Androthi,
The web may be poorly planned and implemented disaster.. but C wasn't going to make it any better. In fact, a lot of the security problems we have in OSes, and web services are caused by using C which is particularly vulnerable to buffer overflows and other dangerous hacks.
The study of computer languages is dedicated to creating more powerful tools to use to express our programs. Functional and OO (and other weirder ideas that have appeared throughout the years) are dedicated to finding succinct ways to write code so that we minimize dependence on architecture, can be more secure, reduce programming errors, while promoting things such as modularity and extensibility.
C was great to get people off their Assembler and Cobol addiction in the early days. But there are far better languages for HIGH LEVEL development today. And there also seems to be better languages for low level development these days as well.
(Note: I programmed in C/C++ professionally for over 10 years.. and still enjoy partaking now and then.. but its important to use the right tool for the job..)
C was awesome back in the 80s when it first became super popular.. we really enjoyed it back then. But we also enjoyed being able to move to real OO languages in the late 90s.
I myself think Smalltalk outdoes any language in existence today, so called "modern" languages are sad imitations that are overly complex (yes even Python and Ruby) and still not as powerful. But I guess I'm in the minority.
if you think you're in the minority, hold my beer:
C is showing it's age and may not be the language with all the bells and whistles programmers have been convinced are the greatest things since sliced bread, but the gist of my comment remains...
if web development was centered around systems programming rather than the scripting nightmare it is today, C would suit it perfectly and you wouldn't need the dozens of convoluted "technologies" that have to work together to get anything done.
i'm not a huge fan of C and we do need something better. many have tried, some have gotten close and others are in the works. i just don't think it's any of the ones you mentioned. and i certainly wouldn't touch smalltalk with a ten foot pole :)
the right tool for the right job? sure. if you spill water, you'll need to invent a sponge to soak up the mess faster, but that old rag can still do the job.
I'm a huge fan of C and use it exclusively these days, though I still like your comment due to good arguments. I hear that Rust might be an adequate replacement for C/C++.
Androthi,
yeah.. some early internet companies started out with C (like Amazon for example).. they quickly saw the light.
If you can do better, by all means, prove us wrong.
But you're kind of going against computer language research, and modern software engineering practices.
I don't know why is everyone so afraid of
C. I am currently in embedded world where almost everything is done in C and haven't noticed any issues or complaints if proper procedures are followed. Of course, it's not as easy as languages which are hardware agnostic, but given the fast paced evolution of hardware, you can know runNode.jsapps even onSingle Board ComputerslikeRaspberryfor example.There will always be fans and groupies of every possible language out there, that's just how human mind works, and affiliating yourself with your viewpoint proponents is our inherent nature.
I am still convinced that C is not going anywhere, and concede your arguments against it. Although, I don't see anyone rewriting
back-endsoftware to any other language any time soon, maybe never.In my opinion, C will stay here until
NLP(Natural Language Processing) finally evolves enough to understandsemantics, and from that point on, the mindset of every developer will evolve into something we cannot even conceive at this point in time. Whether the evolution of NLP will overcome this obstacle and get us closer to creatingAGI(Artificial General Intelligence), this is yet to be seen.We can talk about the present, but I wanted to give you my take on how the future might look. AI may seem powerful now, but it still has a long way to go. Image recognition aside, human languages are still misunderstood and impossible for a machine to understand without the proper understanding of semantics.
I may have gone a tad too far with this; my intention was to mitigate the potential tensions between opposing language proponents :)
I have no problem with C.. I programmed for over a decade in C and C++.
But its not for web programming.. and its not ideal for all scenarios.
I'm not afraid of it at all.
I just think there are better tools for the job.
Of course it's not for web. Maybe with Web Assembly but I think Rust will take over in that specific area, maybe, who knows.
to be fair, C can't be included in a list of "languages that stretch your brain"
it can't be included because C is the granddaddy standard measure. all the other languages are compared to it.
for my list of languages that stretch your brain i would have:
Number 5 will not only stretch it, but probably also displace it 😄
i don't think rust is an adequate replacement for c/c++. it's a language with a very specific purpose.
it's great for writing security software, or software that needs to be proved. i think rust is more in competition with ada. and i kind of prefer ada.
rust just doesn't have the ... agility that C has.
modern software engineering practices gave us the likes of facebook and twitter. both of which have a garbage code base.
just because something manages to steam along as long as you throw the latest bit of hardware at it doesn't mean it's good engineering.
I think I mentioned that once. Just because we have more powerful hardware doesn't mean we have to write less efficient software. Nobody cares about optimisations and memory efficiency these days. I used to play great games on my Atari ST with 1Mb of RAM. It sounds like scifi today, to have only 1Mb of memory.
should have figured.
i started out on the c64, then on to the amiga. in my experience, people who started out with those early systems grew to appreciate hardware limitations and getting every last bit of processing power out of them.
now with everything practically being emulated and a dozen CPUs living in each computer, programmers don't care about resources or efficiency. as long as they can roll something out quickly and it functions relatively fast.
The good old days:
The evolution of a programmer
Damir Franusic ・ Jul 24 ・ 6 min read
I find this comment incredibly ignorant of the history of the origins of Elixir's forerunner, Erlang, which was developed with the sole purpose of solving the real-world task: "Keep the majority of a telecom network running even when a part of it goes down, due to either maintenance, or outright catastrophe."
No amount of meditation on C will remediate that, because if it could, Joe Armstrong wouldn't have needed to invent Erlang.
The right tool for the right job.
I wouldn't try to saw through concrete with a toothbrush (even though it might eventually work).
I think you should add Prolog to your list. That is a language that uses pattern matching to a greater extent than the languages you mentioned and also really forces you to look at programming in a completely different light.
I'll definitely give it a once over! Thanks for sharing!
Since the topic is expanding one's horizons and learning something different I'd have:
Not sure which 2 I'd rotate out, but it would be well worth it.
There is no need to rotate any of them, those exercises would complement any of the above.🤠
Personally I'd love to do that, I didn't go through a CS or CE program and the closest I've been to the hardware is C. 👍
I hope this list receives massive boosts. The line of reasoning for each language is unique, well-considered, and sound. I read a similar post yesterday, extolling Python, C++, Java, JavaScript, and Scala, with the rationale for learning each language essentially boiling down to "it's popular" or "it's easy to learn"... Java was in both categories, without any sense of irony on the "easy to learn" aspect.
While I vastly prefer Elixir's soft approach to type enforcement over strict statically-typed languages (declaring a
@specfor a function allows static code analyzers to warn you when an input or output might not align with what you've said it should be) (also, pattern-matching on function parameters is, in a sense, a means of type enforcement), you've convinced a stalwart proponent of JavaScript's typeless wilderness to dip his toe in TypeScript, where many TS evangelists have tried and failed 👏Oh, I may be wrong on this, but I think you can clean up the fizzbuzz expression you wrote for Elixir, slightly... if you've already tried this and it came back with an error, please do let me know, because I'm actually curious and not near an
iexprompt at the moment 😅I didn't write it, it's from a GitHub repo, but as soon as I'm back to my laptop I will write an Elixir FizzBuzz solution just for you 😉🤠
Ahh, that makes sense too 😅
It's interesting to me to see Typescript and Haskell on the list together. As someone who is working on learning Haskell while using almost entirely Typescript at work, Typescript feels entirely lacking as compared to Haskell.
Typescript's static type checking fixes a lot of type problems in regular Javascript, but falls flat when attempting to work with real data, with many casts, optional fields, and "any" types making their way deep into the program as it develops and ruining the functional benefits of static typing.
Haskell's strict separation of IO from pure functional removes a lot of unexpected edge cases. There's also the common occurrence where, if your complete program typechecks, it's likely to actually do what you intend.
I guess my point is that these languages stretch my brain in different ways: Haskell engages me with interesting mathematical ideas, but Typescript makes me wish I was writing Haskell.
First of all, I would like to thank You for writing this article. Secondly, I would also like to state that arguing about languages is beneath me and please don't get offended as I'm only writing about my experience and conveying my own opinion.
I still notice that many people perceive programming comprising Web only technologies like JavaScript, React, Vue, etc. On the other hand, C++ is considered the most complicated all purpose language that is mostly used for high performance and system programming.
First of all, C++ is not so great and you can say what you will, but template hell aside, C is much faster and cleaner language and if low level and embedded is your thing, there's no other language that will make you REALLY understand how memory, threading and CPU works.
If you are in academic circles, doing some extensive calculations, then GPU or OpenCL will be your best friend, and that is also where C is your only option. The only low level language other than C is VHDL, a relatively new language used for FGPA programming.
So called modern programming paradigms apply only for Web and Mobile world since nothing has really changed, apart from new buzzwords that are basically synonyms for algorithms and/or technologies that have been available for quite a while. There are exceptions of course, but in the case of C++, there is really nothing you can do in C++ that you can't do in C. I accept that some will argue against type safety of void pointers and casting issues but the whole point of low level languages is to learn how stuff really works. If you are aware of endianness, padding, byte boundaries and how pointer arithmetic works, you will begin to appreciate the gained knowledge which will outweigh the initial frustrations of C. GDB and Valgrind are exceptional tools and are only getting better (GCC/Clang fsanitize methods).
I welcome the advances in Web realm, but let's not forget that all that JS is compiled and prepared by Node.js, served mostly by some Virtual Machines running on some *NIX distributions, and ALL of that is written in C. Node.js is a combination of C and C++ but it's core part, libuv, is written also in pure C.
I admire people who are mastering JavaScript and Web technologies because, let's be honest, it's chaos out there. JS is constantly being updated and it's really hard to follow, so I applaud you guys and don't take this as me putting C on a pedestal. I'm just to trying to remind everybody that it took a great deal of knowledge to create such a stable and old language, not to mention compilers, optimizations, etc.
Thank You for reading,
DF
P.S.
Haskell is a special kind of beast :)
C is a great language. I don't believe I said it wasn't, but I will say, not everyone should attempt to master C and it certainly (as some have suggested) is not the best tool for every circumstance.
I actually have written some C code and respect it as the defacto standard for applications where a small memory footprint is of the utmost importance. I do not disagree with you on the majority of your points.
I would have included C on this list, but I wanted to include Rust (which can serve some of the same needs as C) as this article is actually based on the five languages I'm most interested in mastering.
I have actually written a comment about that, and I agree that not everybody should burden themselves with C or C++.
Although I'm a C programmer and do mostly backend network programming involving raw sockets, packet capture, etc., I disagree when newcomers get advised to start from C language because they need to know how memory, cpu and whatever works at the basic lebel. That's great, but that's like saying I need to be a mechanic to learn how do drive. Since most of developments today is web dev which is done mainly in higher level languages like Javascript, there really is no need to burden yourself with all the complexities of C, C++ or any other statically compiled language with manual memory management. Unless you want to go in that direction like me for example or are attracted to embedded devices, stick to higher level languages. This is my opinion and in no way a professional guidance of any sort.
Also, learning all about memory, and CPU in the Von Neumann model is not necessarily reflective of modern computing models. Furthermore, it deprives us of the question of how high level programming should be done. Low level is not the most common paradigm for programming these days. Its more effective Software Engineering if we can hide away details of the architecture and the machine and let the language/platform deal with them. A great example of this is SQL, which although it has its problems as a language, is great at hiding away all the parallelism that goes behind it.
C is generally not considered to be a low-level language, rather assembly is intended with this term.
Calling VHDL new also sounds strange when it's from 1980. VHDL (1980) and Verilog (1984) are two hardware description languages. Their purpose is completely different from general programming languages and I would not classify them together with those. What could be said is that VHDL borrows syntax from Ada and Verilog borrows from C.
Hi and thanks for the history lession. I don't know much about VHDL, but I only used the word 'new' since it became more popular these days with increasing popularity of FGPA hardware. And I would agree that ASM is the real low level language, but let's put everything in todays context when everything is JS alike; in that case, C should be considered a low level language.
I always wanted to try and do something with FPGA, just for the fun of it.
Rust replaces C/C++ on this list. You say there's no other language that will make you really understand how memory, threading and CPU works, but that's no longer true. Since we have Rust now we no longer need C or C++, unless it is to maintain/interact with existing C++ code.
Rust doesn't really replace anything. Still to this date all the important low level programs are being written in either C or C++.
There are plenty of important things being done in the Rust space. There are more than 400,000 line of Rust in Firefox, iirc.
OK please don't make this a language wars thread. I've never used Rust and although it might be awesome, it takes years for a compiled language to become trully stable and get close to being bug free. Firefox is not really a poster child of stability. The best test for any technology, a language in this case, is a test of time.
Rust could become the future C/C++ alternative, lest it become another ghost of a good project. Years ago it was D, now it's Rust; C and C++ aren't going anywhere.
Time is a ruthless judge and jury.
D is not a zero cost abstraction language like C, C++ and Rust are. I was just correcting you on the point that you made about C and C++.
I only mentioned it since it was highly praised not so long ago. What point was that? You mean the test of time point I made?
Ah, just this one:
"there's no other language that will make you REALLY understand how memory, threading and CPU works."
I was just correcting that because it's a common misconception amongst C/C++ programmers. For decades they've deflected competitors like Java, D and Go with the argument that they're nice programming language, but there will still be a place for C/C++ because of its direct reasoning about memory and its ability for zero cost abstraction.
Rust is the first serious competition to C and C++ in this regard. It is a full replacement of C/C++, it does not abstract away anything.
I would also argue your test of time point, but you said you don't want a language wars thread so I'll refrain.
Good point and appreciate the argument. I never claim to know everything and it's always useful to gain extra knowledge. Please comment on the stress of time test, I'm interested in your arguments regarding. What I meant with not wanting language wars is a thread along the lines of "A is better than C", without stating hard facts and reproducible arguments.
Thanks for demystifying Rust for me 😁
Well the argument would be that since Rust is built on LLVM, and actually maps quite closely to the semantics of C, there already is decades worth of production tested compiler infrastructure beneath it.
Of course there still are bugs from the rest of the architecture, but I'd recommend you check out the way the compiler is being built. It is a lot more structured and well organized than most other projects I know of (both open source and commercial), I'd bet we're getting to the point where a new release of Rust has more structured and well thought out decisions made on it then for example C++20 would have, but then I'm crossing into more subjective territory so I won't make any hard statements there.
Well congratulations for sparking my interest in Rust. I understand your LLVM argument in favour of Rust; it has its merits. Also, function arguments in Rust remind me of Pascal which was my first programming language, the one that got me hooked to programming. Who knows, maybe I will finally find a friend for my goold old C buddy 😁. I've done a lot of C++ and it was that final disdain that made me use C exclusively. I'm going to keep my eye on Rust, thanks.
Not all of them.
A good list.
As a Clojure fan I'd recommend it or any other lisp if you want to learn new concepts. Treating everything as data is mind bending in all the right ways.
I'm learning Rust and I also program microcontrollers with C. I agree with you that Rust is the better recommendation given the intent of your article. It brings some novel concepts to the table that C and C++ do not.
In fact, the first thing came to my mind when I see the article title is .. Clojure !
Clojure is a language I'm interested in for sure!
Great article!
We had a Programming paradigms course this semester where we did Prolog, Py, Huskell and Scala (though we went through most langs in an theory overview including all the ones listed in your article).
That was probably the most fun I had programming in the three years since I enrolled in CS. The different requirements the languages themselves put in front off you are a real brain stretch, especially if you've been used to and locked in a single way of doing things (as most people inevitably are due to the nature of CS studies / work on a particular codebase at work). All in all, I find that these paradigm shifts are the best thing one can do to improve their problem solving (which is the most important skill after all).
Thank you very much for sharing. :)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.