Doing what you Love

Bryan Lott published on
4 min, 729 words

Those that know me, know that I love Clojure as a language. The simplicity of syntax and concept draws me like a moth to a flame. It wouldn't be too far to say it's my favorite language and I never have the option of developing anything in it.

I started with Clojure several years ago when I got fed up with the Python threading/multiprocessing pain. While it wasn't exactly the easiest language to learn, the community and the resources available online made the transition reasonably painless. I also probably have an advantage that I was never formally trained in object oriented principals or design and most of my training was either self driven or on the job so switching from object oriented to functional was much easier.

However, I've wanted to use Clojure on a daily basis in my role as a programmer almost since I started learning it. My team, management, and other developers, however, constantly push back on it because "it looks weird." Not kidding, that's a direct quote.


My frustration with this was building on a daily basis. It was triggered moreso because of the simplicity of the issue. 99% of the pushback against Clojure was due to the parentheses being on the left side of the function:

# this was deemed to be simpler/easier to read
"\t".join([str(i) for i in range(100) if i % 2 == 0])

'0\t2\t4\t6\t8\t10\t12\t14\t16\t18\t20\t22\t24\t26\t28\t30\t32\t34\t36\t38\t40\t42\t44\t46\t48\t50\t52\t54\t56\t58\t60\t62\t64\t66\t68\t70\t72\t74\t76\t78\t80\t82\t84\t86\t88\t90\t92\t94\t96\t98'
;; than this
(clojure.string/join
  "\tab"
  (filter even? (range 100)))

"0\t2\t4\t6\t8\t10\t12\t14\t16\t18\t20\t22\t24\t26\t28\t30\t32\t34\t36\t38\t40\t42\t44\t46\t48\t50\t52\t54\t56\t58\t60\t62\t64\t66\t68\t70\t72\t74\t76\t78\t80\t82\t84\t86\t88\t90\t92\t94\t96\t98"

Note than in the Python version there are 4 groupings (parens and/or brackets) whereas in the Clojure version there are three groupings. Tell me again about how many more parentheses there are in Clojure?

In addition, if you can't move the opening paren to the left side of the function and still read it, you've got bigger problems than what I can fix:

str(1)
"1"
(str 1)
"1"

Yes, I realize that these are both contrived examples, but they illustrate the core point of my frustration. Clojure is not harder to read, it's different. And if you can't or don't want to learn something new then you're in the wrong profession.


So, because no one else was interested in learning it or supporting it in production, to ease the discomfort I was feeling with being stuck, I forged ahead anyway. But, I did so with caution and pragmatism. We had a very small issue that was plaguing us for some time. A Python process would every once in a while log a traceback. We had no out of the box way of getting at the full text of those tracebacks in any of our metrics, logging, or reporting tools as Python tracebacks span multiple lines. In addition, the process would retry a given number of times so not all tracebacks should be pushed to the visibility of the engineering team, necessitating some custom logic. The existing alerting pushed notifications to Slack, but without the full text of the traceback and it pushed all tracebacks, not just the critical failures and left out some important debugging details.

As an isolated, non-mission critial (the other alerts would continue as-is for some time) task, this seemed like a perfect location to introduce Clojure as a solution.

Github: Tracebackfilter

It's now been in production for close to 2 months now and has been working like a charm. In addition, no one has derided the fact that it's written in Clojure. Not only did I really enjoy writing it, it's become a gateway for showing other people what Clojure looks like that's actually in production!


Build what you love, even if it goes against the grain, but do it pragmatically. It's the only way to push us forward.