Are you looking for a better front-end coding experience? I’ve just spent several weeks completing my first project with the Elm language. This is my experience. (Spoiler alert: It’s pretty positive.)
I’m a hobbyist coder. I work with software developers as my day job and envy their skill and dedication; I can sit down with a developer and talk unit tests and design patterns, but they’re the professional coders, not me. I code in my limited spare time for fun.
Here’s what I found…
To test out Elm I decided to revisit an application I’d previously implemented in the now-defunct JavaFX Script. The results of that older project are written up elsewhere on this site.
The application is a visualisation of the topic keywords in the Guardian’s Open Platform API. It shows how much is written about a particular topic, and its relationship with other topics. Because two dimensions are insufficient to represent the closeness of multiple topics I let physics do the work for me—the topics are represented as bubbles, pulled together by invisible springs whose lengths represent their relative proximity. As the springs settle down the result is an optimal, if imperfect, representation which is just a lot of fun to explore. Go ahead and try the finished application yourself.
As a first project for a casual coder in a new language it’s a bit ambitious, but I was still attached to the concept and my JavaFX Script experience was unsatisfying, so the itch still needed to be scratched.
Reading Elm was a challenge
Elm syntax is very lightweight and generally free of symbolic cruft. So much so that whereas one language might describe a function f that depends on x and y as f(x, y) Elm says “we don’t need those parentheses and commas, they’re clutter” and uses just f x y instead. It’s much simpler.
But while the syntax is clear, I found the semantics challenging. I struggled to understand seemingly simple code written by other people. I would read map F xs and recognise it as “apply function F to every element of xs” but I couldn’t understand where the function F was defined. And then it would turn out that (say) when you defined type F the system also defined a function F for you at the same time.
In the end I had to write down all my little discoveries so I wouldn’t lose track of them. You can see my Elm Explained pages on Github.
But this is not like the learning curve in Scala or some other languages. Although I felt the curve was steep it was also short. After a few days of working through the little puzzles there was nothing else to learn.
I’d like to think I’m not too bad at functional coding. I do that with Scala pretty much all the time. But Scala isn’t pure functional. It will allow you to create side effects such as writing to a file or making a database call in the middle of your application. And looking back, my own Scala code is pure-ish functional, with side effects near the top of the application, but not strictly outside it.
Elm, on the other hand, is pure functional, and I found that gap between mostly functional and entirely functional a significant one. Elm doesn’t allow any side effects within its applications—all side effects must be pushed up and out the top of the application, and they are dealt with by the external (browser) environment.
The concept of pushing all side effects up and out required a significant mental shift. I hadn’t realised how much I’d relied on the little wiggle room that Scala had given me. Again, the learning curve was finite, but it wasn’t trivial.
Another significant moment was my horror—and I do think that’s the right word—at discovering the purely functional approach to generating random numbers. At one point I thought it would be a bit of fun to throw in some randomness to the application—something like making a bubble’s size random. Then I looked at Elm’s random functions…
In my simple world you would have a random number generator, and each time you called it you’d get a random number. But that’s not purely functional, because in a purely functional world calling the same function with the same inputs must give the same results. So Elm’s purely functional random number generator requires one input (the seed) and produces two outputs: the random number and the next seed. To get the next random number you have to take the output seed, feed it back through the application, and then in again to the generator where you use it to spit out the next random number and the next seed. And so on. So I couldn’t just “throw in” a random number, because it required extensive rework of my app. I gave up on the random idea pretty quickly.
Working code, every time
Well, almost every time. For the first two or three weeks I had the very weird experience that every time my code compiled successfully it did exactly what I wanted the first time I ran it. It was uncanny. This was entirely new in my experience of front-end coding. Of course, due to my struggle with the syntax during that period getting it to compile wasn’t trivial, but I got past that.
The magic stopped eventually, when I managed to compile something that didn’t do what I expected. But I’d say over a period of two and half months using Elm it worked first time about 98% of the time.
Some other minor observations…
Elm is not an object-oriented language. I thought that would feel like a step backwards, but actually it’s just fine.
I didn’t miss the for-loop. I’d been coding with Elm for about six weeks before I realised it doesn’t have the staple of most programming languages… and it never occurred to me until then.
Refactoring is easy. Because Elm is strongly typed you can refactor with confidence. Any mistakes reveal themselves pretty quickly when you recompile.
Writing cross-browser compatible code is a pain in the wazoo. Unfortunately Elm still doesn’t help here. I tend to work with Firefox on Windows, and I thought my application was almost done until I tested it on Chrome and Internet Explorer. Ouch. So fixing that took a chunk of time. It still doesn’t look great on IE, but it’s not terrible. I have no idea how it looks on OSX. And it hardly works at all on touch devices—sorry.
Finally! A modern language for the front end
Finally I feel I can write front-end code with something that feels modern. Yes, I found elements of the learning curve steep, but relatively speaking they were short. I don’t think my code is particularly elegant, but for the most part I can say I’m now comfortable with Elm.
Most of all, I’ve found a language for the front end in which I feel the time I spend with it is productive.