Elm is a great functional language that brings this paradigm to the front-end world. In this post, I will try to report on my first steps with it while building a simple game-of-life. If it goes well there will a few follow-up posts to implement more functionalities and play with more features (web-socket, firebase, …)
I won't retrace the first baby steps to create the project and to get started with the language: check out the elm-tutorial for that! They did an awesome job and explained that perfectly. I'll rather focus on the problems and solutions that I encounter while trying to my first "significant" project with Elm hoping it will help others on this path.
A quick start
Inspired by the official documentation and tutorial I started out my code as simple and concise as possible. I ended up with that code. Nothing fancy here, nothing to report either. From there let's move on!
First "surprise", generating a random board to kick the game cannot be done at initialisation. It shouldn't have been a surprise if I had grasped the entire chapter about this package. Anyhow, to generate a random board for our game, we need to create a generator that will be passed to a command and elm will take care of sending us a message once it is done.
The function randCell tranform a boolean generator into a cell one which we will then use to generate our board in the initialisation:
So we kind of end up with a 2-step initialization: load an empty board but send the command to generate a random board and send us a BoardUpdate message when it is done. After that we just need to update our update function to account for this new message:
So far I was rather pleased by the simple fact of starting to work with Elm, it's simple and it's neat.
The simple game and introducing some changes
After a couple of hours and of tinkering on how to implement the actual "algorithm" of the life game, I ended up with this version of things. Nothing fancy, or extraordinary, the implementation is rather messy and could/should be done in a better way but that wasn't my point. I wanted to see how easy it would be to keep things in place when introducing changes hence the idea: What if the board cells could have 3 states (just for a better UI/UX)? It would be:
- Alive: there is a living thing in this cell
- Dead: some previously living thing just died (i.e. at the previous Tick)
- Empty: there is nothing in this cell
The good and the bad of Union Type
The first step was of course to change the union type Cell to add one constructor to it: Dead. That worked brilliantly: one change, one save and the compiler was telling me where to repair what I had broken: just like in the doc! Awesome!
But being a developer I tend to be lazy and I had the misfortune of finding out that like many functional / advance languages, Elm has the "default" pattern matching operator _ … Which is both great and bad.
- Great'cause in most cases Dead cells behave like Empty cells so I just needed to use the _ instead of Empty in my case ... of and voilà, it worked!
- Bad'cause now that I have some _ all over the place I lost the nicely programmer friendly errors from the compiler telling my I need to take care of the new case in my union type…
Not clear? Let's take an example. This is the part where I filter the list of all the neighbour of a cell and check which ones are alive so I can update the cell's status properly:
Ok? The Empty case that was there before has been replaced by _ which in our case more or less translate by Empty|Dead . Problem now: I want to add another state (e.g. Garbage ) that would change the way I count my neighbours. I would not get any warning on this case ... of because of my _ that would match the Garbage state. Edit: I made a post about that and how to handle these cases better.
We are reaching the end of this first post, next stop will be about putting some interactivity to that game: The user will be able to define the starting board and will see it play out. But before closing this post, here are a few things I found and that are gonna be covered in the next post.
elm reactor is a nice way to get started but what if you want to use a package like elm-mdl and get some CSS or JS library? Well good luck with that, to the best of my knowledge at least I haven't found an easy recipe to do so with elm reactor. I don't really need to take out the heavy weaponry and start setting up a webpack build either: just use elm-live! Takes 5 min to read the doc and figure out how to create your index.html file and you are good to go (plus there is an auto-reload right out-of-the-box!)
I am an adept of clear code organization to a fault. I tend to lose precious minutes/hours/days just because the code doesn't look clean and it is not properly organized. Anyhow, when starting to prepare my Elm app for the game of life, I quickly ended up thinking I'll need to have some "sub-modules" in my code rather than following the tutorials and example code setup.
After a few unsuccessful attempts at coming up with my own organization I ended up on this piece of art: blog.jenkster.com/2016/04/how-i-structure-elm-apps.html Just go read it already!
That's all from me for today!