Hacker News new | ask | show | jobs
by dimgl 995 days ago
Anecdotally, I think Elixir/Erlang are too difficult/esoteric compared to other languages. That makes it hard to come back to after not touching it for a while, which means it'll be incompatible with a lot of devs that use other languages. When I come back to Golang, I can pick it up almost immediately, so I often use it for personal projects. It also has great concurrency primitives, which is one of Elixir's biggest selling points.

Where does that leave Elixir then? It's too difficult to come back to easily, plus it's too different from other languages, and it _feels_ like it doesn't necessarily do anything better than Golang, even if it does (I know it does). This makes it hard to justify the cognitive overhead.

I also think Elixir is really refreshing as long as you stay within the bounds of what you can easily look up online. Once you step out of what’s readily available it becomes _immensely_ more difficult relative to other languages. Last I used it I was also frustrated with the amount of times I had to drop into some Erlang bits to use a library, and the Erlang things it keeps were also hard to wrap my head around (why are GenServers named Genservers? Name it literally anything else)

For all of those reasons I just haven't been able to go back to Elixir. Its model of programming is just too esoteric and different for me to be able to integrate it into my stack.

2 comments

Mind sharing a specific example of what made it difficult to come back to? Was it control flow, a specific library like Ecto, no types, etc?
There were several things:

* The entire model of state with Genservers

* Pattern matching made my code unreadable

* Libraries that I needed had Erlang documentation

I created some pretty gnarly code when pattern matching authorization cookies for some Plug middleware I made. Plus I had to dive into some Cowboy stuff, which had really awful documentation at the time.

"Just use Phoenix!" is what most people will say. But I simply don't want to use a big framework for a straightforward server.

Again, I realize that Elixir is probably really good at what I need it for. For instance, my latest project is a collection of Go binaries that all run at once and process data back and forth. This can likely modeled as processes under a supervision tree in Elixir as multiple Genservers... but Jesus. That's so much harder for me to think about.

What if I want to scale a specific worker up/down? With a Golang binary I can just... launch more containers with the binary. Elixir on the other hand has its own orchestrator of sorts with BEAM. So what do I do here? I guess I need to launch more Elixir servers with my code and then configure something so that it launches more processes of a certain kind within my fleet, but I have 0 effing clue how.

Edit: going through the docs, I just remembered another thing: most of the things I design are dependent on a store of some kind, whether its Redis or Postgres, or any other store. That can be confusing when the Elixir docs have a focus on its own state solutions, like GenServer or ETS.

About your pain points

* The entire model of state with Genservers

Yes and no. They are very useful. Too bad that they insisted following Erlang with that handle this / handle that nonsense (sorry if it sounds snarky) instead of building a better abstraction for the usual scenarios of creating a de facto object and calling methods to mutate its state.

* Pattern matching made my code unreadable

Pattern matching actually made my code much mode readable. I had a large web app with less ifs than the fingers of my hands. I wish I had that kind of pattern matching on function definitions when I code in Ruby and Python for my current customers.

* Libraries that I needed had Erlang documentation

This is true. The point is that many Erlang libraries had no Elixir version. Maybe the new languages on the JVM had the same problem with Java jars. Luckily translating from Erlang to Elixir is almost a 1:1 syntactical matter so it's usually easy to understand what a library does.

Edit:

> What if I want to scale a specific worker up/down?

Running BEAM inside docker was getting popular the last time I developed in Elixir with Phoenix. The project I was working on was considering to run the app in a Kubernetes cluster. We already had workers running in a docker container but I can't remember how we were spinning them up. Some service on Google Cloud.

Agree with Go sentiment. Not only that, it is a great general purpose language that does great with any heavier computational load stuff too.

I do everything with Go and Node+TS. All API services, real time / notifications, and crunchy stuff happens with Go. Node+TS handles anything else for either 3rd party things (usually the node sdk is far superior in terms of documentation and support) or one off scripts.

I've tried phoenix. End of the day I don't want to work with something which is built on something else which I don't know/understand to an even bigger degree. And fwiw, I don't see the point of deep diving into erlang/beam when Go basically does everything plus more, within its boundaries. Reminds me of JVM, you can code all day in Scala (like any junior engineer) but at some point either when shit hits the fan or incompatibility strikes, you need to learn Java and JVM internals.