3 key differences between Elixir and Ruby?

Hey Everyone
Brand new Elixir developer right here!

Excited to join a new community of developers, especially in such a new language. I figured I’d jump in by asking you all a question that I think is super interesting, which is:

In your opinion, what are 3 key differences between Elixir and Ruby?

Obviously there are a ton of differences since they’re completely different languages, but it seems like a lot of people (myself included) come to Elixir from a Ruby background, so it seems like this would be a good topic-especially for newbies like myself-that a lot of people could learn a thing or two from.

It doesn’t need to be 3, just threw that number out there. Looking for really anything and everything that those of you who came from Ruby found along the way, whether that’s big picture stuff like FP vs OO or really random small differences you’ve come across along the way. I’d love to hear it all!

I’ll get things started with a list of my own, keep in mind I just wrote my first line of Elixir three days ago so it’s all going to be super basic stuff, but here it is anyways:

  1. Variable Immutability

This has been a bit of a mind f*** for me. I’ve been trying to get in the Functional Programming / Elixir mindset by solving basic algorithms (without the help of Enum methods) and on more than one occasion I’ve felt completely trapped by the language. I’ll come up with like 6 different solutions, and each time I’ll think I’ve finally figured it out, only to realize half way through that the whole thing relied on mutating one obscure variable somewhere. Hopefully it comes more naturally soon.

  1. Lists are not Arrays

They might look look them and act like them but at the end of the day they are very different. Arrays are index based collections of values, whereas lists are Linked Lists, meaning every list is made up of two things, a single element (the head) and smaller list (the tail)

  1. Dot Notation on Maps

Ok so this one is super small but tbh it’s one of my favorites, and something that I’ve wished Ruby could do since like day 2 as a developer. When you create a map using atoms as keys (which is syntactically almost the exact same as creating a hash using symbols) you can access a specific key by using dot notation on the map ( key_value = %{ x: 1}; key_value.x #=> 1) instead of the Ruby way ( key_value = {x: 1}; key_value[:x] )

  1. Programming paradigm. Elixir runs on the Erlang VM (BEAM) that has a totally different way of running things. Code is run in small processes that are pre-emptively scheduled. This means you can easily take advantage of parallelism without being able to hog a core/scheduler, and you can write blocking code without having to worry about it blocking some other code from running.
  2. Functional programming with immutable values. Changes the way you think, for the better IMO.
  3. Pattern matching. I use it in conditionals, I use it in function heads, I use it in assignments. It makes my code more readable and helps guard against (runtime) type errors, failing fast instead of running with a possibly wrong value and crashing far away from the problem site. Now to be honest I haven’t played with Ruby much so I don’t know how they mitigate that.
6 Likes
  1. No return - it is a challenge at first,
    but very rewarding once you learn to live without it.

  2. No member variables or inheritance - all the parameters to your function are explicitly passed in, much clearer!

  3. Library ecosystem built for concurrency - ever been bitten by a Gem that wasn’t threadsafe? Works in dev/test then fails when running in Puma. Not in Elixir :smile:

3 Likes
  • Pattern Matching & Multiple arity functions
    I now wish every language had this, it’s de-structuring, plus sort of a powerful “value/format-enforcement” mechanism (pattern) that can be used anywhere, function declarations, case’s, assignment, etc. The clarity might not be obvious at first but really becomes obvious once you need to keep adding functionality.

  • Direct access (sometimes cleaned up in terms of boilerplate) to Erlang’s OTP Abstractions and Tools, like gen_server and ETS. These two alone allow a sh**load of stuff to be done in relatively simpler ways.

These 2 are things I constantly use - one in terms of writing in the language the other in terms of architecting with the language.

Then the traditional, runs on the beam, etc etc etc, but there’s plenty of other stuff…

3 Likes

You can btw work without implementation inheritance / subtype polymorphism in oo languages. Recommended.
Paper Do We Need Inheritance? from Wolfgang Weck and Clemens Szyperski:

3 Likes

Completely agree with point number 2. It’s crazy how much just one week of trying to learn Elixir has changed they way I think about programming. Things that used to seem normal just seem plain wrong now, in particular passing/mutating collections by passing their reference to a separate method just feels gross to me now. After using Elixir it seems so obvious how much cleaner it is to just match a new variable to the output of the function, but I didn’t even give it a second thought for my first three years as a programmer.

1 Like

Haven’t even gotten in to the stuff from #2 yet but I can’t wait to see everything Elixir is capable of, but I whole heartedly agree with pattern matching / multiple arity being a game changer. I genuinely got excited when I was watching a tutorial and saw someone type this line:

“def calculate(arr) when length(arr) <= 1 do”

Never seen anything quite like it before.

1 Like

While being present in Ruby with Lambdas, I find really nice to play with functions. I guess it’s one good side of functional programming. By extension, I also enjoy the pipe operator, so common in unix shell, and the with construct…

2 Likes