Barriers to Entry and Awesome Things About the Elm Language

elm

This week, I gave a talk at San Diego JS about the advantages and barriers to entry of the Elm language. For those who might be curious, this is that talk in post form.

If you’re unfamiliar, Elm is a relatively young language that compiles to JavaScript. It is functional, its data is 100% immutable, and it is incredibly strict about data and types. The dominant community standard for architecture for an Elm app is somewhat similar to a React/Redux stack in JavaScript.

Before getting to the good stuff, let’s talk about the common barriers to entry to getting into Elm.

Barriers to Entry

Weird-Ass Syntax

length : List a -> Int
length list =
  case list of
    [] ->
        0

    first :: rest ->
        1 + length rest

There’s no getting around it, Elm’s syntax is weird. No commas between function arguments, commas at the beginning instead of the end of lines (though this one is a community standard and not a requirement), etc. It’s weird, and it takes some getting used to.

Functional Thinking

If you’re used to object oriented languages, getting used to thinking entirely in functions can be jarring, and it can take some time before it starts to feel natural. This isn’t an issue unique to Elm, but it’s still going to be an issue if you haven’t tried functional languages before.

Using JavaScript Libraries

Elm is not JavaScript. Directly calling JavaScript functions is not possible in Elm. There are ways to use JavaScript libraries with Elm, but instead of calling functions directly, you’ll have to fire events from your Elm app to your JavaScript and back.

More Work Up Front

The Elm compiler is incredibly unforgiving. I’ll talk later about why I think this is a very good thing overall, but there’s no denying that in the beginning it means more work. You’re required by Elm to handle many possible failure cases of your code before it will even compile.

Essentially, it’s literally impossible to put off things like accounting for a possible null value, because if Elm detects that it’s possible for a piece of data to be null (or, in Elm terms, Nothing), the code will not compile until you write code that handles that possible case.

Alright, that all out of the way, let’s get to…

The Good Stuff

Phenomenal Errors

Elm gives hands-down the best errors I’ve ever seen in any language. They will all give you:

  • the line number
  • a visual of the line
  • a visual indicator pointing to the specific function or part of the line the error occurred on

And some of them will give you:

  • Misspelled function or variable name suggestions (see above image)
  • Hints for why an error may be occurring (e.g. with a type mismatch on an equality check, you might see this hint: “Hint: With operators like (==) I always check the left side first. If it seems fine, I assume it is correct and check the right side. So the problem may be in how the left and right arguments interact.”)
  • Predictions on what you might be trying to do and explanations for why it may or may not work (an infinite recursion error on “x = x + 1″ will suggest you may be trying to mutate a variable, in which case, it reminds you, you cannot mutate variables in Elm)
  • Links to even more elaboration on concepts (the infinite recursion error will offer you a link to this page for further reading: https://github.com/elm-lang/elm-compiler/blob/0.18.0/hints/bad-recursion.md )

More Confidence in Your Code

In short, moreso than in any other language I’ve used, if my code runs, it almost always does what I expect it to. The compiler errors are so thorough and specific that once I’ve gotten my code to a state where they don’t happen, it usually just works. It’s almost eerie.

Less Defensive Coding

Along the same lines, the thoroughness and strictness of the compiler eliminates a lot of the potential places where you might be tempted to code defensively in other languages. Not sure if that variable will exist when it gets passed into that function? Good news: in Elm, if it’s possible for something to not exist (i.e. to be Nothing), your code literally won’t compile unless you handle that case. By the same token, it’s essentially impossible to write a case statement that doesn’t handle every possible case.

Easier Refactoring

Functionally, the compiler’s strictness is like having a large body of test coverage built in to the language. Generally, when I start refactoring, I’ll break a lot of things, and I’ll follow the compiler errors just like I follow test failures when refactoring in other languages.

The World’s Most Endearingly Polite Package Manager

It asks you things like “May I add that package for you?” when you ask to install things:

image

And “Do you approve of this plan?” when it works out version compatibility before installing:

image

It’s adorable.

JavaScript Interop Isn’t That Bad

There’s no question it’s a layer past just calling a function, but it’s a pretty straightforward layer. Just firing events and listening for events. If you’ve done it in JavaScript in other ways, it should feel pretty familiar.

Humans-first

The first thing that attracted me to Elm was the errors. The creator, Evan Czaplicki, spent two months working out how to make the errors as useful as possible, and it shows. Moreso than that, it shows that there is a deliberate focus on the ease of use of the language, which makes me optimistic about the future usability of Elm as it evolves and about the Elm community.

These things also make me optimistic that the community will be friendly, which is as important for any language or tool as the tool itself. I prefer communities that prioritize people over code, and I think language decisions that focus on people are a signal that focusing on people is a community value. I think there is more evidence of that priority the more changes I see made in the language.

Try It!

In conclusion, Elm is great and you should try it if you’re looking to try something new.

Here are some places to get started:

Also, lately, I’ve been trying out using Elm to build Electron apps. If you want to try that, I’ve open-sourced a basic skeleton with some example code here: https://github.com/neurodynamic/brunch-with-elm-and-electron