Stefan Arentz

Finding your way home with Clojure

Learning a new technology is much more fun when you actually have a mission. So I decided to make a little web app that can show the departure times of streetcars in Toronto.

This is possible because the City of Toronto has made the NextBus API available as part of its Open Data initiative, which provides info about routes, stop locations and arrival time predictions.

You can see the end result in the screenshot below, or try the app yourself on my test server. (If it is down, clone the code from Github, it is very simple to run the web app)

Many thanks to Sean Martell for his superhero CSS skills to make it look so good.

Like my previous Clojure experiment, this app also uses the Angular.js framework on the client side and Ring, Compojure, Chesire and clj-http on the server side.

There is a good chunk of XML parsing in the app using clj-xpath and I also implemented a very basic geo-spatial database that currently has a naive find-objects function, but is plenty fast. (Less than a millisecond to find stops in a database with more than 10000 entries. Yay for JVM speed.)

The app has two modes of operation:

  1. Location based - where it will ask your browser for your current location and then show departure times for streetcars and buses within a 250 meter radius. This is the default. See Demo (Only finds stops if you are in Toronto)
  2. Preconfigured stops - this uses a list of stops that you can provide. The current app has two, one for where I work and one for where I sometimes play. You can change the list of stops in index.js and reference a configuration by putting it's name in the location hash. See Demo

The project is open source and you can find the code at https://github.com/st3fan/departures-board

Clojure & Angular.JS Recipes Demo

I'm getting back into Clojure and web app development and so I am hacking on a bunch of small projects to learn the technology.

The first app that I am making available is a simple web application project that uses the Angular.js framework and Twitter Bootstrap on the client side and Ring, Compojure, Chesire and clj-http on the server side.

It's functionality is pretty minimal: it just grabs a list of recipes from Recipe Puppy and then displays those in a table. You can change the main ingredient to load different recipes.

I think it is a decent example of how to mix together Clojure technologies to get an app that exposes JSON APIs for an Angular.js front end.

Although most of my (Mozilla) work is still in Python, I a really liking, and prefering, Clojure at this point. The language is beautiful and packaging and deployment are so much better than in the Python world.

Code is at https://github.com/st3fan/clj-angularjs-recipes

Verbose Regular Expressions

Did you know that Python's regular expression engine has a re.VERBOSE option? It allows you to specify expressions like this:

pattern = """
^
(He|She)              # pronoun
\s+
(likes|hates|loves)   # verb
\s+
(cheese|bacon)        # object
$
"""
match = re.match(pattern, "He likes cheese", re.VERBOSE)

Instead of:

pattern  = r"^(He|She)\s+(likes|hates|loves)\s+(cheese|bacon)$"
match = re.match(pattern, "He likes cheese", re.VERBOSE)

This can make a huge difference for complicated expressions. And now you can comment them too, which is always nice when you have to find out what that regex did that you wrote 3 months ago.

Preventing Long Lines

One of my pet peeves is preventing long lines of code. I usually code at 120 columns but I still prefer to keep lines short for readability and better understanding of code.

Here is a simple tip that works really well for long conditional statements.

Say you have a function like this:

def process_numbers(numbers):
   for number in numbers:
      if number not in BAD_NUMBERS and ((number >= 0 and number <= 10) or (number >= 100 and number <= 110)):
         do_something(number)

But maybe this is more readable:

def process_numbers(numbers):

   def in_ranges(number):
      if number >= 0 and number <= 10:
         return True
      if number >= 100 and number <= 110:
         return True

   def is_good(number):
      return number not in BAD_NUMBERS

   for number in numbers:
      if in_ranges(number) and is_good(number):
         do_something(number)

So I refactor the logic into inline functions. It is more verbose but I generally prefer that over condensed code. The inline functions are short and concise and implement simple tests. And if you need the same logic in more than one place then simply move them up into global scope.

Python List Comprehensions

List comprehensions are a very concise way to create lists out of iterable things. They are awesome and you should really use them where possible because they can make your code much less verbose.

Their general format is:

result = [expression for item in list if condition]

The list comprehension simply loops over the list and if the optional condition matches it will evaluate expression and append it to the result list. So you can very easily combine iteration, filtering and processing.

For example, instead of the following:

# Get a list containing the lengths of the strings
lengths = []
strings = ["cheese", "bacon", "eggs"]
for s in strings:
   length.append(len(s))

We can write:

# Get a list containing the lengths of the strings
strings = ["cheese", "bacon", "eggs"]
lengths = [len(s) for s in strings]

Combined with a filter is becomes clear how powerful list comprehensions are:

# Get the max age of all cats
max_age = 0
for a in animals:
    if a.type == 'cat':
       if a.age > max_age:
          max_age = a.age

Which we can reduce to:

max_age = max([a.age for a in animals if a.type == 'cat'])