Working on updating elm-lang.org made me consider what the quintessential Elm experience is and how to present it, and I’m wondering what you all think. What are the best things about Elm? What is the experience of those qualities?
On top of my head:
Confidence: I absolutely love the feeling of “if it compiles, it works!”
Same architecture, infinite possibilities: The ability to navigate any Elm program immediately
Incredible styling libraries: No exactly core to the language, but I love that about working in Elm!
No configuration: I almost take this for granted by now, but it is SO easy to install and setup Elm. This permeates the community too- most packages + tools come with such well thought out defaults and needs little to no configuration!
Data structures first: Elm prompts me to define and think about my data as the first thing- this is made me such a better programmer!
The error messages: A classic that I almost forgot haha every time I do something in Haskell or JS, I immediately miss the thoughtful Elm error messages!
Let me know if you have additional points + more elegant rephrasing, or second one already mentioned! Thank you in advance and have a wonderful weekend!
It’s groundbreaking: Many of the ideas from the Elm community have sent ripples through the entire tech industry- I am grateful to be part of a community which values creative thinking and is willing to try an unwalked path. It has already born amazing results and I’m confident we will continue to innovate and improve. <3
My favorite thing about Elm is that its simplicity and powerful guarantees make it possible to create reliable, useful tools for working with Elm.
elm-format is stable and almost always behaves how I want it to. This is something I’ve come to appreciate while working in F# and finding that the formatter there is more buggy and prone to messing up my code. I suspect this is due to how much more complicated F#'s syntax is, and therefore how much more difficult it is to write a good formatter for it.
In elm-review, I can think of a static analysis rule and then implement it in Elm code and often it just works. I doubt this would be possible if there were many ways to write the same thing in Elm or if there were lots of extra language features I’d need to account for in my rule.
Likewise, I don’t think Lamdera would be possible if Elm had an escape hatch for writing mutable or side effectful code.
I feel like Elm highlights simplicity. In api design, the language helps steer you towards writing api’s that are simple and clear. This feeds back into the feeling of writing in Elm. It feels great and is actually fun to write.
Beyond these, I love how fast Elm is. I make a change and I get an immediate response. It’s like I’m having a conversation with the compiler about how best to build things. Another, and I’m not sure how to word it, is how easy it is to jump back into any Elm project after not looking at it for months. Or I guess how easy it is to jump into any Elm code base since.
Everything in core fits together like Lego. I guess that is the big plus of the development model of elm where one person has a plan and complete overview. I think that also influences other libraries. It is easier for package developers to align with core style/thinking if core only contains one style/thinking and not a mix of different contributions.
Fearless refactoring. Whether its renaming a function or a type, or making a drastic change in a core data type, you just follow the compiler errors and come out the other end with a working app. This is the only way to grow and sanely maintain an app over the long term.
The type system is a tool for thinking about your problem.
Yeah the refactoring is the big one for me. I do big refactorings now and then with no problem and little refactorings almost constantly. My last React app is, in terms of what it can functionally do, very simple and I’d still much rather refactor my biggest, orders-of-magnitude more complex Elm app than refactor that one.
Something I don’t hear as much: libraries don’t tend to break underneath your feet when you update them like they do in other languages, and when they do change it’s usually a much quicker fix. None of those “this was working the last time I worked with it and I haven’t changed anything why is it suddenly not working???” moments.
It is a very well balanced language. Small syntax but very expressive, but not overly complex. It is the most productive programming language I have used.
Excellent software engineering possibilities - by which I mean the ability to break code up in a modular way. This is possible on multiple level through functional programming techniques, the module system, and the package system. Its great for building small and large systems, with confident refactoring.
Automatic semantic versioning of packages.
Strong type system eliminates many programming mistakes. Forces programmers to account for all error pathways in code, not just the happy path.
No runtime exceptions.
Elm code is maintainable without it being a big headache.
What I love about safe refactoring is that it relieves me from the pressure of getting everything right from the beginning. In my experience, the conciseness and type-safety Elm provides, allows the architecture of my app to find itself and naturally evolve with new product requirements.
Thanks to Elm, now I just go and build things in peace. It’s wonderful.
Union types and record types let you model data really, really precisely.
If it compiles, it works.
Option/Result instead of C null pointers or python None or…
Great compiler errors (except for Rust traits.)
It’s not JavaScript
Unlike Rust:
Modules rather than Objects as the cornerstone of abstraction.
It compiles really, really fast.
No macros (and no runtime codegen, e.g. Rails/Django) means it passes the Grep Test.
Small language
You can learn it in a day and keep it in your head even if you don’t use it for a few weeks. (Maybe I’ll eventually internalize all the different magical Rust traits but…)
The language is (mostly) not a puzzle box – you focus on solving the underlying problem, even if there’s boilerplate, rather than trying to shape the problem until it fits into the language’s “optimal” spot (e.g. Rust generics and traits.)
Tiny footprint.
Rapid install time.
[EDIT TO ADD:] Exceptions are not part of the language at all. (Rust has “panic!” which is somewhere between exceptions and longjmp)
For me elm is all about making you think about your application as a whole, everytime I build something in elm, I’m forced to think about the domain more carefully, handle all possible cases and gain a deeper understanding of how the application should behave in various scenarios.
Without elm, I routinely have an incomplete picture of how the application should work and only after several round of bug fixes does the application work as intended.
One of the most important things to me, that is also one of the most complicated to communicate, is the feeling of joy and relaxation when writing Elm code.
Reading through the points here, it strikes me that the various points can vary greatly depending on how you use Elm.
For instance, in the last two years, I’ve been working on the same Elm project, and prior to that I’ve been working on two big AngularJS projects. So I rarely, if ever, start something new or look at other projects, whether in Elm, JS, or TS. And I’ve never been on a JS project that hasn’t at least been well architected.
In that context, what I really appreciate about Elm is:
fast and precise compiler feedback
excellent tooling (elm-format, elm-review, the Elm IDEA plugin, etc.)
strong focus on readability - keeping things simple