Before my now-previous employer folded, we were being courted by a buyer (boy,
was that time period an emotional roller-coaster!). This would have changed our
development direction somewhat, and so at the behest of my boss I spent a couple
of weeks exploring language options for our upcoming greenfield projects.
I was asked to explore Clojure and Go, and compare them to our existing
language, PHP. I decided to evaluate the languages by porting a fairly
stand-alone portion of our existing app into both Go and Clojure, and comparing
it to the PHP version.
The Basic Problem
That relatively stand-alone portion of our app was our recipe importer. It
would allow users to import recipes from external sites, for use within our
There are a number of standards for recipe formats: the hRecipe microformat,
schema.org's Recipe format, RDF, data-vocabulary.org's Recipe format, and
probably a few others. In addition, most of the sites we explicitly supported
either fail to mark up the entire recipe, interpreted the spec they purported to
follow in strange ways, or merely referenced a recipe from another site,
requiring us to follow the link chain to a parsable source.
In other words: it's a real (non-toy) problem, it's sufficiently complicated to
get a reasonable feel for a language, and it's simple enough it can be ported
within a relatively short timeframe.
I spent a week in each of Clojure and Go. This was not enough time for a full
feature-parity port with the PHP version, but sufficiently long to present most
of the complexity of the problem (inheritance, parser registration, and so
Inheritance Is… Uh… Missing?
Neither Go nor Clojure support "classical" OO inheritance. It may be my brain
is broken through years of shoehorning things into inheritance hierarchies, but
it seems to me this particular problem happens to be a pretty good fit for
classic OO. "Site X uses format Y, with these overrides."
So the biggest stumbling block in both languages was simply coming up with a way
to model the problem. To be perfectly honest, the solution I ended up in both
languages looks pretty much like classic OO shoehorned into whatever the
language does support (embedded structs in Go, multimethods in Clojure), and
would almost certainly not be considered idiomatic by people with more
experience in each language. (But then, neither would my PHP, and I've been
doing that for a very long time.)
As a lisper bent on proving that a lisp was a viable option, I started with
I spent approximately three days figuring out how to even model the problem
without classic OO inheritance, and the following two building three generic
parsers and two site-specific ones.
It was one of the most enjoyable weeks of my tenure. Clojure is as flexible as
you'd expect a Lisp to be, the code was compact, reasonably fast, and I was
reminded of how much I'd been missing interactive development.
When I presented it alongside the PHP it was a port of, reactions were mixed.
Some developers remarked that they had a very difficult time understanding it,
and that it would likely prevent the developers who worked on other codebases
(e.g., our mobile developers) from swooping in to make a quick fix. My boss,
who had apparently spent a significant amount of time attempting to do something
useful in Clojure without much success, remarked that the comparison made
Clojure much easier to understand for him than it had been previously.
Next I tried Go. Having already faced a lack of inheritance, and presented with
Go's much smaller field of options to choose from, I was able to jump right in,
and hit parity with the Clojure version in short order.
I did not particularly enjoy programming in Go. While Go is strongly
opinionated in surprisingly good ways, the edit, compile, debug cycle is
obnoxious and slow (goauto may have helped reduce this pain), the code ends up
verbose and repetitive, and there are little to no facilities for abstracting
The Go code received less objection when presented. The lines were
significantly longer than either the PHP or Clojure versions, and vertically it
was very slightly less dense than the PHP version due to all the error checks.
- Code Feel
Is it any wonder I prefer lisps? So much meatier.
- Learning Curve / Programmer Effectiveness
Go was the easiest to pick up, but there isn't really anywhere left to go
once you do. Clojure is definitely harder to become proficient with, but you
can leverage that into increased programmer efficiency later. PHP has so
many pitfalls that anyone starting out is likely to end up negatively
productive at first, writing a horribly insecure buggy mess.
- Developer Emotions
Clojure inspired a mixture of enthusiasm and curiosity, with strong concerns
for the practicality of finding and training developers in a language which
is so different from mainstream ones. Go had an enthusiastic champion in my
boss, but was largely met with ennuitic "meh"s by other developers (golang is
basically boring-by-design). PHP was loved by none and hated by some, with
the only argument for it being "we've already got a bunch of code written in
I liked Clojure. It's fun to write in, it feels very productive, and the power
lisps provide to build your own abstractions is unparalleled. But as varied as
the quality of code was in our PHP, providing room for even more variability
is a hard case to argue. While I would have loved to recommend Clojure, asking
a team of devs who think in terms of C++ to make the transition was more than I
could have sold.
Go, on the other hand, solves a lot of problems that we had with PHP. Stuff the
wrong type? Go would have caught that. Inconsistently-formatted code?
would have fixed that. Bugs because PHP did something unexpected unless you
thoroughly read and retained every aspect of the documentation? Go's house
is not built from bundles of thorns.
So while Go may not be the language for me, it would have been the right call
for our team.
Available For Work
As you may have guessed by the mention of my previous employer folding, I am
presently available for work. Feel free to contact me if you have something you
think I may be interested in.