DEV Community

Cover image for 5 Powerful Programming Languages to Stretch Your Brain
Jacob Herrington (he/him)
Jacob Herrington (he/him)

Posted on • Updated on

5 Powerful Programming Languages to Stretch Your Brain

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
end

(1..100).each { |x| fizz_buzz x }
Enter fullscreen mode Exit fullscreen mode

Resources:

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
  end
end

Enum.each 1..100, &IO.puts(fizzbuzz.(&1))
Enter fullscreen mode Exit fullscreen mode

Resources:

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 {
    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);
  }
}
Enter fullscreen mode Exit fullscreen mode

Resources:

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));
Enter fullscreen mode Exit fullscreen mode

Resources:

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]
Enter fullscreen mode Exit fullscreen mode

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! 🤠

Top comments (97)

Collapse
 
vimmer9 profile image
Damir Franusic • Edited

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 :)

Collapse
 
kaddkaka profile image
kaddkaka

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.

Collapse
 
vimmer9 profile image
Damir Franusic

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.

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him) • Edited

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.

Collapse
 
vimmer9 profile image
Damir Franusic • Edited

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.



Thread Thread
 
aminmansuri profile image
hidden_dude

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.

Collapse
 
tinco profile image
Tinco Andringa • Edited

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.

Collapse
 
kamit28 profile image
Amit Kumar

Rust doesn't really replace anything. Still to this date all the important low level programs are being written in either C or C++.

Thread Thread
 
jacobherrington profile image
Jacob Herrington (he/him)

There are plenty of important things being done in the Rust space. There are more than 400,000 line of Rust in Firefox, iirc.

Thread Thread
 
vimmer9 profile image
Damir Franusic • Edited

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.

Thread Thread
 
tinco profile image
Tinco Andringa

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++.

Thread Thread
 
vimmer9 profile image
Damir Franusic

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?

Thread Thread
 
tinco profile image
Tinco Andringa

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.

Thread Thread
 
vimmer9 profile image
Damir Franusic • Edited

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 😁

Thread Thread
 
tinco profile image
Tinco Andringa

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.

Thread Thread
 
vimmer9 profile image
Damir Franusic

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.

 
tinco profile image
Tinco Andringa

Not all of them.

Collapse
 
tetsuoii profile image
tetsuoii

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.

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

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.

Collapse
 
thepeoplesbourgeois profile image
Josh

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.

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

The right tool for the right job.

I wouldn't try to saw through concrete with a toothbrush (even though it might eventually work).

Collapse
 
aminmansuri profile image
hidden_dude

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.

Collapse
 
androthi profile image
Androthi

that's because the web is a poorly planned and implemented disaster.

Thread Thread
 
jacobherrington profile image
Jacob Herrington (he/him)

Seems to be pretty successful to me, but I get what you mean.

Thread Thread
 
aminmansuri profile image
hidden_dude • Edited

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..)

Thread Thread
 
aminmansuri profile image
hidden_dude

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.

Thread Thread
 
androthi profile image
Androthi

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.

Thread Thread
 
vimmer9 profile image
Damir Franusic

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++.

Thread Thread
 
aminmansuri profile image
hidden_dude • Edited

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.

Thread Thread
 
vimmer9 profile image
Damir Franusic • Edited

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 run Node.js apps even on Single Board Computers like Raspberry for 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-end software 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 understand semantics, 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 creating AGI (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 :)

Thread Thread
 
aminmansuri profile image
hidden_dude

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.

Thread Thread
 
vimmer9 profile image
Damir Franusic • Edited

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.

Thread Thread
 
androthi profile image
Androthi

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:

  1. assembly
  2. prolog
  3. forth/factor
  4. clojure
  5. eh. maybe thrown BF here, just for giggles.
Thread Thread
 
vimmer9 profile image
Damir Franusic

Number 5 will not only stretch it, but probably also displace it 😄

img

 
androthi profile image
Androthi

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.

Thread Thread
 
androthi profile image
Androthi

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.

Thread Thread
 
vimmer9 profile image
Damir Franusic

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.

Thread Thread
 
androthi profile image
Androthi

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.

Thread Thread
 
vimmer9 profile image
Damir Franusic
Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

Exactly ☝️

Collapse
 
slu profile image
Søren Lund

That's a nice list. I'm stretching my brain with some Perl 6 programming. Perl 6 is very expressive and includes features like:

  • Object-oriented programming including generics, roles and multiple dispatch
  • Functional programming primitives, lazy and eager list evaluation, junctions, autothreading and hyperoperators (vector operators)
  • Parallelism, concurrency, and asynchrony including multi-core support
  • Definable grammars for pattern matching and generalized string processing
  • Optional and gradual typing

Here's my version of the FizzBuzz written in Perl 6:

sub fizz($i) {
  print "Fizz" if $i % 3 == 0;
  print "Buzz" if $i % 5 == 0;
  print $i unless $i % 5 | $i % 3 == 0;
  print "\n";
}

fizz($_) for 1..100;
Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

My boss is a Perl developer, or at least was before he started writing Ruby, I really appreciate Perl's expressiveness. I've thought about picking it up to build some fun tools before! Thanks for including a code snippet!

Collapse
 
jj profile image
Juan Julián Merelo Guervós

Perl 6 (perl6.org) belongs to the same family, but it's a totally different language. Much more expressive, too.

Collapse
 
thepeoplesbourgeois profile image
Josh

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 @spec for 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 👏

Collapse
 
thepeoplesbourgeois profile image
Josh

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 iex prompt at the moment 😅

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

# or possibly

1..100 |> Enum.map(&fizzbuzz) |> IO.puts
Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

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 😉🤠

Thread Thread
 
thepeoplesbourgeois profile image
Josh

Ahh, that makes sense too 😅

Collapse
 
bretthancox profile image
bretthancox

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.

Collapse
 
sakesun profile image
Sakesun

In fact, the first thing came to my mind when I see the article title is .. Clojure !

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

Clojure is a language I'm interested in for sure!

Collapse
 
aminmansuri profile image
hidden_dude

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.

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

I'll definitely give it a once over! Thanks for sharing!

Collapse
 
grazhevskaja profile image
Alexandra Grazhevskaja

To stretch the brain more - I would advise to write your own compiler or language.
Yes, this is a big job!
One of my IT professors, who is already 70 loves to do that during his summer holidays.
At summer he goes for a 1-month rafting trip, takes his laptop and writes a new compiler! 👴👨‍💻

Collapse
 
vimmer9 profile image
Damir Franusic

It's in my todo list, hopefully not the bucket list 😂

Collapse
 
grazhevskaja profile image
Alexandra Grazhevskaja

That’s great, wish you to succeed!😊
Do you already have the ideas on your language?

Thread Thread
 
vimmer9 profile image
Damir Franusic • Edited

Not really but I'm sure it will come to mind one day. I have written parsers, lexers and interpreted DSLs (Domain Specific Languages), but never really needed to go one step further and create the actual compiler. Even if I find the time and stamina to try it, it will serve no other purpose, apart from making me feel more competent about my skills.

All of this is based on the assumption that I emerge successful from this endeavor. There's always a chance of everything ending in disaster with me crying myself to sleep surrounded by wild hordes of bugs which have found their new spawning ground, my brand new co-called compiler. 😊

Thread Thread
 
grazhevskaja profile image
Alexandra Grazhevskaja • Edited

You have a really wide experience!
You are right. Usually such experiments with compilers is something that happens in academic environment. Actually, I worked on my DSL being a post graduate and there is no guarantee it will see the real world one day.
But, anyway it always makes me feel proud of my self! 😊

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

That's a project I'd like to complete this year actually!

Collapse
 
grazhevskaja profile image
Alexandra Grazhevskaja

That’s cool!
I had some experience in developing a programming language, but that was the DSL (Domain Specific Language).
Share with us your progress, very interesting to know.

Collapse
 
tristanred profile image
Tristan Dubé

Nice article, I would have chosen the following construct for the Rust example since pattern matching is more idiomatic in Rust than a bunch of if/else.

Something like this :

fn fizzbuzz(i: u8) {
  match i {
    x if x % 15 == 0 => {
      println!("FizzBuzz");
    },
    x if x % 3 == 0 => {
      println!("Fizz");
    },
    x if x % 5 == 0 => {
      println!("Buzz");
    },
    _ => {
      println!("{}", i);
    }
  }
}

Its not quite as compact as your example but you can remove a level of indentation by just having one liners like x if x % 15 == 0 => println!("FizzBuzz"), if that's your thing.

One advantage to pattern matching in Rust is that it forces you to exhaust all possibilities when comparing values. This avoids forgetting the else or a particular case for a number.

Excellent article !

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

Thanks for sharing! I didn't actually write the FizzBuzz solutions, they are from a GitHub repo. I appreciate your input though, super useful 🤠

Collapse
 
youngsteveo profile image
Stephen Young

You should cite your source in the article.

Thread Thread
 
jacobherrington profile image
Jacob Herrington (he/him)

Way ahead of you, I already did! It's in a comment in each snippet.

Collapse
 
vosmith profile image
Vincent Smith

I love this article. I've touched all of these languages at least once with the exception of TypeScript which I would like to try. I really liked Elixir and its Supervisor tree, it definitely stretched my brain. I put in a strong effort to get good at Rust (the borrow checker won the battle, but the war is far from over). I couldn't stretch my brain far enough to grasp Monads and Functors for Haskell though. That one finally broke me.

I hope these languages keep growing. I'll keep them in my tool chest.

Collapse
 
wardaft profile image
WarDaft

I'm always sad to see people get tripped up by Monads, and especially by Functors. They're necessarily simple concepts that are almost always explained poorly.

Functors are things you can map/apply a function over. Exactly no more, and exactly no less. Lists are Functors because you can apply a function to each element of a list. Maybe is a Functor because you can apply a function to a single element after checking if it exists. Functions are Functors because you can apply a function to the result of a function. 'Void a' is a Functor because you can apply a function 0 times to something that does not exist. The Functor typeclass exists so that we can say that we don't care which of these (or other) things we're dealing with. If you have a structure, and you can write some plumbing code to take a function and apply it around your structure, you have a Functor. Note that something either is or is not a Functor, it's not actually up to you to decide, just like you don't get to say the number 3 is even. It is, in essence, simpler than actually thinking about the particular structure you are mapping over, because that particular structure has additional implications beyond what Functor implies.

Monads are not quite as simple, but almost. They're usually explained in terms of return and bind on some bizarre example ("Monads are like burritos!"), but bind is a more complicated operation that's implemented for performance reasons, rather than ease of understanding. Functors need one thing (mapping) but Monads need 3. First, they need Functorness - if it's not a Functor, it can't be a Monad. Second, they need to be Pointed, or injectable - if you have some random value, there should be a trivial way to cram it into the Monad and this is currently called 'return', but in the future might be called 'pure'. Lastly, they need Join, or flattenability. The injectability means you can just keep wrapping more and more layers of the Monad around a value - you can have the number 1, a single element list containing the number 1, a single element list containing a single element list containing the number 1, and so on ad infinitum. Join does the opposite, save that it can't get rid of the last layer - you don't need to know how to 'exit' the Monad, just simplify it. In Haskell syntax, that means you know how to go from [[1]] to [1], but you don't need to go all the way to 1. That's it, those are the three operations that make a Monad. There are some rules about how Monad instances should behave - Functor had them too but the type system is good enough that you can't accidentally break those. The rules are 1) that 'return' must really be trivial - if you stack a bunch of layers with return, then join them back down, nothing should change and 2) if you have a bunch of layers, the order you join them in should not matter to the final result. In terms of list, return makes a single element list, and join is just a single layer flatten - and it doesn't matter what order you flatten things in, you always get the same list at the end. In equational terms, 'x == join (return x) == join (fmap return x)' and 'join (join v) == join (fmap join v)'. If this sounds scary because of 'fmap' here, just try to remember that by using fmap we remove all possible considerations except that it's something you can map over - it is mapping distilled to its most basic possible form. Individual Monads have their own interesting behaviors, but those have nothing to do with Monad itself, which is nothing more than what I have described here. Monad is ultimately a fairly simple concept that gets bogged down with specifics that you don't need to think about for the core subject. Monads are implemented in terms of bind, where 'm >>= f' is ultimately the same meaning as 'join (fmap f m)', but the latter possibly constructs and breaks down an intermediate structure, and so can be prohibitively slow in practice.

Typically, the aha moment for Monads is not when people grasp the complexity, but rather fully realize they can let the complexity go.

Collapse
 
vosmith profile image
Vincent Smith

Thanks WarDraft! I'm still unsure about Monads lol, but your last statement put me at ease. Maybe it's best to not try so hard to understand it, and let it show me 👍🏾

Collapse
 
konstantinklima profile image
Konstantin Klima

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.