Hacker News new | ask | show | jobs
by phtrivier 2724 days ago
Elixir has great things "of his own":

* the syntax is well though-of (`with`, destructuring, `|>` are powerful

* message passing has great use-cases

And then it has problems that are not necessarily "elixir-y", but are there nonetheless:

* it's hard to model an application around the Actor model. It's very easy to abuse it.

* it's hard to maintain / refactor a large application without help from the compiler before run-time

* it's hard to maintain an application in a language with a young ecosystem and no "seamless" integration with a better established one (ports are not seamless.)

Quite frankly, I'm looking forward to writing a backend in Rust, to have a point of comparison.

5 comments

Thanks for these notes. I’m suspicious of unconditional praise for any technology, and a lot of the goodwill for Elixir seems like it’s biased by the intention to promote adoption of the language, or like it’s from people who haven’t encountered or paid attention to its problematic aspects. Seeing fundamental problems listed like this does more to convince me that it is a real and serious technology (one with a compelling set of strengths, no less).

As for Rust, do try it out. Haskell-esque type checking, the “anti-OO” interpretation of C-style conventions, and memory safety without garbage collection are a seriously potent set of features, but it can be frustrating when you find out yet again that your whole day of R&D leads somewhere incompatible with its philosophy, and is therefore a dead end. I’m building a Rust webservice framework as a hobby/learning project, but it wouldn’t be my first choice for a production API under active development. On the other hand I’m not aware of a better choice for an embedded daemon process or a stable microservice.

> I’m suspicious of unconditional praise for any technology, and a lot of the goodwill for Elixir seems like it’s biased by the intention to promote adoption of the language, or like it’s from people who haven’t encountered or paid attention to its problematic aspects.

I realize that the tone of this GitHub post has been a bit fanboy-ish and biased but you have to understand that your comment here is biased as well. It's non-objective to dismiss a technology because somebody couldn't articulate it as well as Mark Twain would. Most people simply aren't that good at articulation -- me included. Doesn't mean that what they are trying to articulate is invalid, wouldn't you say?

As for "fundamental problems" -- it's a case of "pick your poison" as usual. There is no universally good language. If you frequented the official Elixir Forum you would know that most of us use other technologies every day. Many people in the forum have 10+ years of experience and are well-aware of the big picture. We are very realistic about when Elixir is a good fit and when it isn't. There's a plethora of posts where we straight up advise somebody not to use Elixir.

IMO practice critical thinking and don't judge by the tone of isolated articles.

As a final point, you should also consider why the language has so much fanboy-like articles. Maybe it is doing something good for real? Objective thinking demands consideration of all major possibilities.

I've found CQRS and DDD designs fit well with OTP and elixir. The actor model with pattern matching ends up cutting away a lot of the classical OOP DDD details.

The issue I see is carryover from other ecosystems taking paradigms that aren't necessary and don't fit into libraries and patterns. It feels like there are still conventions to settle on.

The fact that it's dynamically typed is also often overlooked, while it's at the top of my deal breaker list.

The programming world is strongly moving toward statically typed languages, because today, there's pretty much zero reasons to use a dynamically typed language.

> The programming world is strongly moving toward statically typed languages

How? Python and Javascript (not Typescript) are two of the most popular languages in the world and still growing very fast by many accounts. Which strongly typed languages are taking over?

I guess you're not a regular HN reader? :) Many HN commentors routinely think that they are "the programming world", which is rather far from the truth.

For years, dynamic typing has been hyped on HN, while statically typed languages such as C# were routinely scoffed at.

Something in the air has definitely changed recently, with many discovering the very trait they eschewed is actually a major boon - very likely because they had only ever dealt with JavaScript. My guess is this is primarily driven by the growing popularity of TypeScript, Rust and Go.

> Something in the air has definitely changed recently

- Type inference becoming commonplace is an important factor. Previously it felt kind of silly in statically typed langs to supply some of the things compiler could figure out.

- Strict null checking becoming commonplace increased confidence. Previously, even if your code compiled, you would still get null pointer exceptions.

- Type checking became kind of opt-in with langs like TypeScript.

- Statically typed langs used to be associated with heavy IDE's previously. Now you can use most editors and get the benefit of compiler within the editor through language servers.

These are some great points I hadn't considered, thanks
Pattern matching is strong typing. It just doesn't assert on a type alone -- it also asserts on the shape of the data itself. Example:

    def handle_data(%{
      customer: %{
        date_of_birth: %NaiveDateTime{} = dob,
        account_balance: %Decimal{} = balance,
        name: name,
        count_purchases: purchases
      }
    }) when is_binary(name) and is_integer(count_purchases) do
    # work with the data here
    end
^ This both asserts on a particular data structure (a map with a "customer" key containing at least those four attributes) and asserts on the types of some of the attributes. I find it pretty handy and practical.

---

But I concede that strong+static typing eliminates a class of bugs preliminarily. That is unequivocally true.

I agree and believe that it's harder to maintain a dynamically-typed codebase, but Elixir has a well-thought-out gradual typing solution: typespecs ( https://hexdocs.pm/elixir/typespecs.html#basic-types ). This builds on Erlang's Dialyzer tool and is supported by editor plugins like VSCode's ElixirLS extension. In practice, you do get instant typechecking while you code, if you write down the typespecs properly.
Debatable in practice, given the lack of a type system that actually enforces checks -- Dialyzer's even less complete, not to mention its poor error messages.

Elchemy, Alpaca, and Gleam try bringing static typing to the BEAM, but they're still too immature, unfortunately.

Agreed, but even with the above issues, Dialyzer still gives you, let's say, more than 50% of what you'd be getting with an ML-like type system.
Purely anecdotal: our experience with Dialixir was rather disapointing (slow, lots of false positive, hard to express types coming from external libraries and generated code.)

Unfortunately, the tradeoff at the time made us stop using specs altogether.

Surprised to hear about false positives, that's supposed to be impossible by the design of Dialyzer (it only reports provable type errors).
Static typing incurs restrictive boilerplate while only eliminating a small subset of all possible bugs. I will admit the guarantees it gives you are nice but I’d argue that the guarantees immutability-all-the-way-down gets you in a language like Elixir are stronger. You don’t get those guarantees on ANY of the statically-typed languages that run on the JVM because as soon as you interop with anything Java, bye-bye guarantees.

And this is anecdotal but with good pattern-matching and guards in Elixir, I can’t remember the last time I created a bug that would have been made impossible by static typing.

> Static typing incurs restrictive boilerplate

Wrong, type inference has been aa thing for decades.

Rust is much much less mature for writing backends.
`|>` comes from F#.