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.
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.
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 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!