Hacker News new | comments | ask | show | jobs | submit login
Learn Elixir with a Rubyist (IV) – Types, Data Structures and Pattern Matching (joaomdmoura.com)
158 points by joaomdmoura on Jan 19, 2017 | hide | past | web | favorite | 59 comments

As a Ruby programmer trying to take a look at Elxir, i still find it hard to read. Maybe functional languages take time to get used to but it doesn't seem as "clear" as procedure or oop style. I know the added benefit of speed and concurrency, but for most apps we build it is not needed for now.

Do any Ruby programmer find Elxir easier to write or read? Im genuinely curious to hear about this because a lot of Ruby devs are writing Elixir.

I'm a proficient Ruby developer (with code in production since 2004).

Ultimately I find it's easier to go back to some Elixir code and understand what it does, compared to Ruby.

The main reason is (to me) the fact that I now see Ruby object instances as "living things" (with always something hidden underneath, that can change), while Elixir types are more like "stable messages".

So yes, I believe doing Elixir maintenance is ultimately going to be easier than with Ruby.

(Note that I work with both Elixir & Ruby now, and also with Node & other platforms, I don't intend to stop using Ruby at all).

I slung Ruby 2008-2015, and started using Elixir heavily in late 2015. Aside from simple scripts that typically involve shelling out to Unix utilities, I find Elixir easier to write in just about all cases at this point. The syntax is even more consistent than Ruby's (to the point that it's homoiconic) and the language docs rule. Once you get a few concepts like pattern-matching and pipelines under your belt, it gets easy.

It was helpful that I wrote a bunch of Scala from 2013-2015, so I was familiar with working in an immutable FP style -- that made it a gentler transition for sure.

What have you found hard to read about it? The community is still settling on what code style "should" look like, so maybe you saw some funky Elixir, or maybe it's something deeper.

> What have you found hard to read about it?

Not the OP, but: keeping state: Agents, GenServers etc. FP/immutable approach does offer some great advantages, but also makes some otherwise trivial stuff (say, something akin to setting an ivar in Ruby) convoluted and tough to read.

Elixir does make you think hard about the global state you keep. It's an "eat your vegetables" decision, and I've acquired the taste. Keeps me out of trouble when designing things. Contrast this to Ruby, where class variables and globals are all over the place and thread safety is a pipe dream. [EDIT: it's not that Ruby-the-language forces this worldview, but Ruby-the-community adopted it and most Gems show the effects of that.]

As far as ivars, you'll have to work hard to emulate that. There are no classes or instances. Probably you want to just use a map or a struct to represent an instance and its state.

When comparing programming languages, it is extremely common for people to mistake familiarity for other things like "clarity" and "simplicity". When looking at code with unfamiliar conventions, they often proclaim tremendously simple, clear code to be "complicated" because it is not what they are accustomed to --even when an equivalent implementation in their fav language would be much more obtuse.

I don't claim to know about your personal situation. Just throwing out a relevant observation.

Ya, in that point, everyone should watch the Simple Made Easy talk by Rich Hickey, creator of Clojure. One of the best talk ever in my opinion.

I've been working full time on a rails app for the last 2+ years.

About 3 weeks ago I dove into Elixir for a big rewrite of a side project as a learning exercise. In the beginning it feels strange, mostly because of the functional way of thinking required and some new types to get used to (structs, keyword lists, etc.). Once you get the hang of it however it feels really, really nice. I dread going back to my rails app now... Others in the thread have stated most of the reasons why so I won't go into that.

I'm looking forward to launching this re-written side project in a few weeks and seeing what the performance is like. (This is currently a stale Django app). Running locally in dev mode the performance (Phoenix) seems like it will be excellent.

I find Erlang itself to be pretty easy to read and write, if a bit repetitive/verbose at times. There are not very many 'magical' things happening; it's all pretty clearly spelled out. Elixir is mostly an improvement on Erlang unless people are getting crazy with the macros.

While learning Elixir and Phoenix, I found Cowboy source code easier to read with no knowledge of Erlang other than what's inferred from learning Elixir than Phoenix's generated app scaffolding.

In Erlang, I look at 'module_name:function_name' I can simply open the module file and look at the function definition.

In Elixir, I had to ask "Was this function aliased?", "Is it imported from a module? Which module?", "Was it imported/aliased through a use statement?" The code was more concise, but harder to read IMO. Of course you can simply reference functions by their full name in Elixir as well, which is what I'm doing with my own code.

Phoenix tends to do .... interesting things with macros. It's not your typical Elixir application.

I find my IDE to be helpful in this situation, since all macros are compile time and thus can be unwrapped by the IDE.

What IDE do you use for Elixir? Thanks.

I use IntelliJ and Atom. I'm actually still deciding which is better.

Can the Ruby people please stop blogging about Elixir and explain things relative to Ruby? There are way too many 'Elixir-for-Ruby-programmers' tutorials on the net already.

Elixir is pretty great and enthusiasm is good but I feel this leaves a large group of people in the dark.

Consider that content can have way more potential to be educational and interesting when crafted with a specific audience in mind. For an Elixir post, that audience need not be "all programmers". I see nothing wrong with the author's approach and would gladly welcome more writing of this style.

Perhaps what you mean to say is that you'd like to see more folks in your own communities writing about Elixir with your relevant needs and perspectives in mind.

Why do they have to stop blogging internet is fairly open you have an option to not read things that are not of interest to you. (BTW. I am not a Ruby developer)

The last thing I want Elixir to be is shoehorned into the web app space and community of Ruby, but it seems inevitable. Oh well.

This might be a controversial thing to say, but Ruby would be a pretty obscure language today if it wasn't for Rails.

If you want Elixir to remain obscure as well, keep hoping that it doesn't get picked up by web developers and Rubyists.

I for one want the language to eventually overtake Ruby in popularity (hopefully with Phoenix overtaking Rails). So yeah, the more individuals and communities that adopt it, the better.

I've been writing Elixir for almost a year, and have yet to build a Phoenix app. I did write a Plug hello world app once, just to see if my container was wired up correctly.

Amen to that. Ick.

If you think there are too many Elixir-for-Rubyists tutorials around, wait until you look for Ruby-for-Rubyists blogs.

If you had to make a comparison, what would be the pros and cons of using elixir vs node.js?

I'm currently working in both. If we are just talking about them in terms of their respective merits, Elixir is my preference. It has a wonderful compiler, pipes allow for composable chains of logic, the Phoenix framework is wonderful for web development. Literally every interaction with it I've had has made me think "wow that's just a great example of excellent programming taste...". In terms of scaleablilty, I've heard stories of a single server able to handle millions of requests. Not personally been able to verify that (nothing I've done in the language has reached that kind of scale sadly...). Once you get used to pattern matching, you'll wonder how you ever lived without it. The community is amazing and supportive. The language creator Jose Valim has responded to my emails directly which is really cool.

With Node, you can cobble together pretty much everything I've described (except for maybe pattern matching) above but it's a bit of a kluge IMO. You can program functionally. And you can make yourself a kind of "compiler" via linting or perhaps by using Flow or Typescript. I've yet to find the experience fluid or pleasant. The language is just not designed for that stuff. ES6 is a huge improvement that said. And before you go thinking I am a node hater, I love JavaScript and use it all the time. I'm just painfully aware of its shortcomings because of how much I work with it.

My biggest issue with Elixir is that it's hard to set up a proper CI/Deployment pipeline. It CAN be done and I've done it but nothing "just works" like it does with Node. Try dockerizing a phoenix app or setting up a heroku instance to see what I mean. All of these things work but it's an obscure language so one needs to be more advanced to understand and address problems in that area.

To sum up: very excited about Elixir and hope it continues to grow. If I was starting a new project I would probably use it.

You mention setting up a Phoenix app in Docker so I'll link to a couple of posts I wrote describing how I do that: https://dev.bleacherreport.com/starting-a-phoenix-project-wi..., https://dev.bleacherreport.com/brunch-in-a-container-phoenix.... I almost always start new Elixir projects in Docker for local development now, and deploy the images to Elastic Beanstalk. If you're not setting up a cluster it's not a bad option.

At Bleacher Report, we've definitely reduced operating costs on some of our services by switching to Elixir and running on fewer/smaller machines, and we routinely pick Elixir for new services now. But we also recently launched a Node service which could handle all frontend traffic on a single server, so in some ways it's hard to say whether the gains are more due to the technology or improvements in the service design.

Thanks for the links! I've successfully Dockerized Elixir apps now but I'm always looking for new and better ways to do things. I'll check your stuff out and see how my approach stacks up. Thanks again!

I'm working on both too, and one point that I faced was the Node 1.5GB RAM limit per node process (at least on Heroku https://devcenter.heroku.com/articles/node-concurrency - I know it can be worked around though, although not on Heroku), which can force you to run multiple processes (aka clustering) depending on your use cases (e.g. thousands of client websockets connections from the process, if you need to listen to a large number of e.g. Slack connections).

This can lead to a more complicated architecture than with Elixir, where a single Elixir process will be able to use more RAM & all the cores, too.

On the other hand, I love the dynamism of the Elixir ecosystem, but it's not yet as rich as Node's one, and it's still harder to find a proficient Elixir developer, than a Node one.

But personally yes: the fundations of Elixir are very, very strong, and I'm investing in it completely (in addition to Ruby & Node, which I already use).

I would disagree with the notion that Elixir's ecosystem isn't as rich as Node's for two reasons:

1. Node has a lot of packages to be sure, but a lot of them are redundant, and a lot of them are packages that overcome some weakness in the Javascript standard library. Elixir doesn't have as many duplicates in its ecosystem, and its standard library is robust enough that you don't have to search for packaged one-liners to overcome some missing feature that should come standard with the language.

2. Node has access to Erlang's standard library and packages. It is also trivial to include external Erlang code and libraries in an Elixir application.

I definitely agree with 1/, yet I was more referring to more advanced functionalities (but I do agree that the "foundations" of Elixir are very strong and I think it will ultimately be a large factor of its success).

2/ Did you mean "Elixir has access to Erlang ..." rather than "Node...", I assume?

I'm well aware of that (I also use Java libraries quite a lot with JRuby etc, similarly), yet having worked with Erlang developers (in polyglot apps), I still personally find that there is more choice for me in both Node & Rubygems, compared to raw Erlang, at least for the topics we had to cover.

Well - I guess it depends on what your actual needs are, YMMV!

Yeah, sorry about the typo. I did mean that Elixir has access to Erlang...

Good points!

> where a single Elixir process will be able to use more RAM & all the cores, too.

I think you mean a "single instance of the BEAM" here as a single Elixir process is pegged to 1 CPU core.

It's useful to think of the work of m Elixir processes being distributed to n cpu cores by the BEAM scheduler. An Elixir process is not a system process in the way we usually think of the word process if coming from a non-BEAM world.

Sorry for the confusion ; by Elixir process I meant a "unix Elixir process" (aka one command you run), not the lightweight Elixir "Process". The unix Elixir process uses multiple CPUs.

Regarding CI/CD pipeline. I found SemaphoreCI pretty nice. It supports Elixir/Erlang without the need for Docker and can deploy to Heroku pretty painlessly using the available buildpack. Got a full pipeline working for a Phoenix app going in about 30mins.

Yeah I started off using that exact pipeline and it worked well. We ended up moving to AWS which Semaphore only supports if its Elastic Beanstalk (could be different now to be fair). We couldn't go that route for more reasons than I care to list here. My hope is that Elixir gets popular enough that we can start to see some first class build tools integrated into more of these products.

Elixir (well I use Erlang but it is close enough).

* I like the concurrency model better. Lightweight processes vs callbacks and futures. I find processes as concurrency units maps better to problems I had to solve. So there is less impedance mismatch. That makes a huge deal in a larger project. (eg.: a user request as an isolated process vs a chain of callbacks). OS design got this right years ago -- think how most modern popular operating systems represent concurrency - an isolated process.

* Safety & fault tolerance. Processes are isolated. So you can build very robust systems. That simply puts money in your pocket just due to ops costs. A non-critical / experimental part of backend is crashing at 4am and restarting? No, problem, keep sleeping. Rest of the service will stay up and you can fix it in the morning.

* Debuggability and inspection. BEAM VM comes with built in ability to debug, inspect and trace out of the box. That has saved so much time (and money) over the years.

* Hot code reload. This is a first class feature. We don't rely on it to do upgrades. But it proved invaluable to fix an issues or two for a high value customer without taking down the services. Or simply to add extra logging to monitor a pathological edge-case.

I think it is important to note that processes are not only isolated at a high level, but also use private memory deep within the BEAM VM; unlike the JVM, for instance, which uses shared memory.

Good point. That is why the analogy with the OS processes. They really are the best of both world -- they are lightweight and also have isolated heaps.

There's a lot of replies to you here but I'm going to touch on the big one.

Node.js's biggest concurrency perk is non-blocking I/O thanks to a cooperative scheduler. When I/O is about to happen, the scheduler relinquishes control.

Elixir has non-blocking everything. Each process is prescheduled making it impossible for a runaway method to completely takeover the process.

The a comparative example server with millions of small requests in each language. An infinite loop in node would disrupt every other request to the server. In Elixir, the other requests would go on as if nothing happened.

The tradeoff to prescheduling is that you'll never hit a top end benchmark with Elixir vs other fast languages, but you'll get a very consistent response time. Makes it ideal for real time work, which is what most servers really are.

There's many more that other folks are describing here. Natural clustering ability due to lack of shared memory, immutability, message passing, etc. Really cheap processes (goroutine = 2k, elixir process = 0.5k) that makes it so cheap that the model is to create two. One as a supervisor and the other as the actual process. If anything crashes the process, the supervisor instantly restarts it.

The combination of the supervisor tree and prescheduling make it possible to run entire applications within the runtime that other parts of the system depend on. Imagine running a database INSIDE of your Node application. Pair that with the natural clustering ability and you get the ideal platform for a self-contained distributed system. Just keep tacking on servers as you grow.

You'll hear the term "OTP" a lot and that's essentially a set of patterns on top of the foundation that I just described that provides best-practices and models for utilizing the stack in different scenarios.

This and the actor model for concurrency goes hand in hand. Not only do you have an pleasant way for writing concurrent software, but you have a foundation (BEAM and OTP) that is built for the concurrency model.

From what I've seen, people investigate Elixir for the functional programming but stay for the concurrency.

Elixir's greatest strength is it's simplicity with modules and it's functional paradigm.

No confusion as to how to import a module and what to namespace it. Just call it. No fuss.

Immutability. Your functions returns transformed data, you don't transform the data itself. That's liberating and makes for such a compelling unit testing experience you find yourself writing more tests to make 100% sure that function does what you want it to do and handle edge cases.

With Node (Javascript), you don't have that. You have a cobbled together solution that works just barely. But how? I don't know.

You npm installed something now the project won't work, you spend three hours debugging and out of desperation you npm install again and now it's working - but why, who knows. Multiply this strange experience to 5 times a day and you get kind of exhausted of Javascript.

Maybe it's not Javascripts fault. Maybe it's Node/NPM itself that ruined the experience, I haven't used Yarn yet.

@aecorredor, there a bunch of things you should consider and that I could use to compare both, in general ppl tend to compare elixir with node because it also enables you to build concurrent apps, but you have to take into account the Erlang VM and OTP, the tools it brings to the table to build concurrent system surpass node.js capabilities of delivering the same thing IMHO. Also don't forget that Erlang and it's VM has 30+ years of intense exposure to different scenarios and apps, and put that together with 30 years worth of open source work and libraries. I'm not saying node.js is bad, or even worse, but maybe both shouldn't be compared because represent different tools for different jobs.

Apart from the other individual language/framework differences others will no doubt give you - Uncle Bob makes some great points on why we should be moving to functional languages: https://www.youtube.com/watch?v=7Zlp9rKHGD4

To summarize his best point: Processor manufacturers are betting the farm on multi-core. They want to increase performance by giving you more running cores, so you should be using a language that makes multiprocess programming easier. Functional languages, especially ones like erlang, do precisely that.

these two vids are pretty great, obviously they favor FP/elixir, but great advise from two expert people.

Elixir Should Take Over the World by Jessica Kerr: https://www.youtube.com/watch?v=X25xOhntr6s

What every Node.js developer needs to know about Elixir - Bryan Hunter: https://www.youtube.com/watch?v=q8wueg2hswA

FP and the Erlang VM gives you a great deal of advantages, which you should be aware of.

Ultimately I would also look into node.js, since it's so popular it's becoming a reference, and jobs for javascript/node are easy to get.


1. Has a better standard library, plus easy access to all of Erlang's standard library.

2. Handles concurrency, instead of having to rely on an event loop, and does so in a clean and accessible way.

3. Makes it easy to communicate between processes, not on the same machine, but processes running on other machines as well.

4. Is faster and consumes less resources.

5. Is easier to create, manage, and maintain code and deployments.

My last point is subjective, but I like Elixir's syntax much, much better than Javascript's.

In my opinion, comparing Elixir to Node is like comparing a Tesla to a high-end roller skate.

This biggest pro for node.js, is the large community. JavaScript is everywhere, there is a literally a stable library for anything you can possibly conceive at this point, and if you're already doing front end, it's an easy pickup.

It does depend on what you are doing - if you are making websites both are fine (although I've seen callback hell implemented in a Node/express website before).

If you have difficult scaling problems that need stateful servers and clever cross server web socket implementations like Phoenix.Presence or 2 million web socket connection on a single huge machine, Elixir with the OTP is more likely to give you tools to build this difficult to scale thing.

Just wanted to say thanks to everyone who replied. Lots of great advice. Cheers.

What's your use case?

I know depending on the use case some tools are better than others, but to clarify my original question, for someone who might just be getting into the back-end and looking towards the future, what would be a better choice to focus on, elixir or node.js? and say for example that the person has done both some Ruby and JavaScript programming, including some basic apps with Rails and Express.

Javascript is a very common language. Elixir is generally a better language, but less popular. If you're looking to get a job you could probably do either but there are probably more Javascript jobs. At the hobbyist level Node might be easier to pick up, especially if you know Javascript already.

I think Javascript is generally a safe bet for the next few years because the Frontend is firmly embroiled in Javascript as well.

Elixir seems poised to keep growing on the backend, so it's probably not a bad one to learn either.

My real advice to someone starting out would be to learn a language but focus on learning general programming and computing concepts through it. The better you are at programming and computing, the more easily you can pick up new languages and switch between them seamlessly.

Also, as you learn new languages, focus on learning the right way to do things in that language. It's extremely helpful to be able to separate programming concepts from language constructs.

All forward looking statements are guesses but... I see a strong movement toward Elixir from Ruby devs (and others, I'm not a Rubyist) and I expect Phoenix to be one of the main frameworks in the next few years. It's due to a combination of simplicity, history (erlang is old), and a change in the types of apps some of us are building. There will always be simple CRUD apps too but the demand for constant connectivity seems to be rising. IoT, desktop replacement apps, etc.

Edit: fixed typo referring to Elixir as a framework

More fair comparison would be Phoenix [1] to node.js

Elixir is a programming language whereas node is a framework.

[1] http://www.phoenixframework.org/

Node.js isn't a framework. It's a JS runtime, and for most purposes can be considered a variation of JavaScript. However, like Go, Node.js has such a rich networking support in its standard library, that some people go "frameworkless" when developing web apps in Node. But not as many as in Go, probably.

Something like Express would be more analogous to Phoenix in Elixir.

Node isn't really a framework, it's a runtime and is fairly close to a language. It's roughly analogous to Nashorn.

True, then in that scenario we should talk about comparing phoenix and express right?

edit: meant to say phoenix, not elixir.

Express and phoenix maybe. Elixir is not a framework. Node is to js perhaps as plug is to elixir. Even that kind of doesn't compare correctly though.

node is to js as beam is to elixir, roughly.

Node is not a framework though

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact