Clojure Coding Dojo in Munich

Yesterday I took part in my first Clojure coding dojo. Here’s what I’ve learned.

Theme

The assignment was to find the way out of a maze. The maze is defined as list of lists (aka matrix), with different types of tiles.

  • 1 start/path
  • :_ floor
  • :W wall
  • :Exit

The algorithm should find the path from 1 to :Exit and mark all tiles on the way with a 1. The result should be the labyrinth matrix with the marked path.

Input:

Output:

Standard Functions and Reuse

The first thing I did was use a tuple of numbers as coordinates. Determining the kind of tile the matrix contains at a certain location is easy. Simply unpack the lists using the integers as keys. This works because vectors are associative data structures. They map the index to the respective element:

But then I realized that the coordinates are also kind of a path into the nested data structure. There already is a function in clojure.core that does that: get-in. The result is so concise that I didn’t even need a separate function for it. I just called:

Yet again I found it amazing that the clojure.core functions are that well reusable. This is due to the fact that Clojure tends to use data everywhere. So as soon as I start representing the things in my application as data, I can reuse an enormous amount of functions.

Data Literals

Next up were functions for coordinates. Namely “up”, “down”, “left” and “right”. The up-function leaves the x unchanged and decreases the y coordinate. This can be written as such:

Data literals are concise. They are

  • are a requisite for destructuring and thus help concision
  • they help make concise notations, e.g. for return values

Sensible Defaults

The next function’s job is to check whether moving in a certain direction is possible. Moving is possible if the resulting location is inside the matrix and at the same time is either floor (:_) or :Exit.

That is easy. Apply the direction function to the current position and see what in that tile.

The first sensible default is that get-in, called with “illegal” indices (e.g. -1), returns nil instead of throwing an exception. That is extremely useful, because I can just call it and test afterwards. So above code can do two things at the same time:

  1. check whether the coordinates are inside the maze
  2. check whether the tile is walkable

But I lamented the “or” a little. Then an idea hit me. clojure.spec uses sets as alternatives.

Meaning a suit is either one of the four alternatives. This alternative is exactly what I needed here. The point is that clojure sets are also predicates. Used as a function and supplied with an element in the set they return true, otherwise false. So above code can be written as:

This is way better. Even better is the following:

A second time sensible defaults (sets as predicates) strike home.

First Class Functions, Symbols and Elegance

The above function is also really elegant in my opinion. Higher order functions tend to feel that way.  This is probably due to the fact that functions in FP languages are first class and can be passed around. Languages without symbols on the other hand suffer. And Clojure even has two kinds of symbols:

  • regular symbols, aka vars, that name something else (e.g. functions or data)
  • keywords that name themselves, like enums.

In my eyes that separation is extremely useful. For example there is no doubt about what to use as keys in maps. It’s always keywords, if possible.

Conclusion

I think it is huge that a tiny project of around 30 lines of code already benefits so greatly from Clojure’s features.

Also I love the clicks-into-place feeling that I get from working on a problem and then finding the solution in something I have known all the time. This effect is far more pronounced in Clojure than in any other Programming language I have learned thus far. Simplicity I guess?

Complete code here.

Leave a Comment

Your email address will not be published. Required fields are marked *

Solve : *
19 − 1 =