This post was originally written in a notebook. Check out Gorilla REPL if you haven't done it yet!

A sizeable number of Clojure developers had some Common Lisp experience in the past. When asked what the main Clojure advantages over CL are they often mention having a single equality operator (compared to Lisp's eq, eql, equal, equalp). It might come as a minor point, but in practice, it is very cognitively exhausting to keep track of which one you should use. What's, even more, jarring is that eql — not the most intuitive one — is usually the default. Can you explain with a straight face to a beginner that their string-keyed hashtable didn't work because it was created with a wrong equality operator? I never could.

But Clojure has a similar sin of its own — the multitude of list type predicates. If woken up at 3 A.M. and asked what the standard Clojure data structures are, you would likely name lists, vectors, maps, and sets. But how do you tell if the given object is a data structure of a certain type? "Well", you'd say, "there are vector?, map?, set?, and… list?? Leave me alone, man, I'm trying to catch some z's."

Gotcha! The thing is, list? is a weak predicate. It checks if the object is precisely a PersistentList, but there are plenty of things in Clojure that look like lists without being ones.

Read more ->>

TL; DR: Omniconf is a new configuration library for Clojure that unifies environment variables, command-line options, and config files; and ensures the configuration is complete and correct before the main application code runs.

Configuring your application is often a daunting and thankless task. It very much depends on the way you launch your program, so it is difficult to solve the configuration problem for the general case. Twelve-factor app guidelines suggest using environment variables for everything, but that rule is unnecessarily rigid. If you have many options, configuration files are more appropriate. When you launch the app from the command line (on a dev machine, for example), command-line arguments are preferable. But now you suddenly need a unified access to all those configuration sources.

There are already libraries that solve the configuration problem in Clojure, namely: Environ, Aero, Nomad, Fluorine. All of them are quite good at what they do; however, we at Grammarly needed extra functionality — to check the final configuration state before the main program executes, and make sure there are no missing or incorrect options. What began as a few helper functions were extracted into a separate library and called Omniconf.

Read more ->>

Until now, Boot documentation had imperfect instructions on how to setup Boot to fully work with CIDER. I've updated the page to include a better way which separates regular repl (launched from terminal, better be quick to load) from the heavy CIDER repl with all the necessary dependencies. Here we go, add this code to ~/.boot/profile.boot:

(require 'boot.repl)

(deftask cider ""
  (reset! boot.repl/*default-dependencies*
         '[[org.clojure/tools.nrepl "0.2.12"]
           [cider/cider-nrepl "0.10.0"]
           [refactor-nrepl "2.0.0-SNAPSHOT"]])
  (reset! boot.repl/*default-middleware*

Then in Emacs do M-x customize-variable cider-boot-parameters and set it to cider repl -s wait.

Read more ->>

Clojure 1.7 finally saw a feature many people have been asking for — reader conditionals. It enables writing of platform-independent reusable code, where by platforms I mean Clojure, CLJS or ClojureCLR. With reader conditionals you can write code like this:

[1 2 #?@(:clj [3 4] :cljs [5 6])]
;; in clj => [1 2 3 4]
;; in cljs => [1 2 5 6]
;; anywhere else => [1 2]

This is cool, but unfortunately the list of features is currently limited to just three platforms. Additionally, the only place where you can use this syntax is inside .cljc files. So, goodbye to leveraging this from the REPL. Hint by @mfikes: it works in REPL launched directly from Clojure jar, but for some reason it doesn't in REPLs spawned by neither Leiningen nor Boot. Yet, most people use REPL from those tools, so we're still screwed.

On the other hand, Common Lisp has feature expressions as a first-class feature. Developers are free to define their own features and use them anywhere they like. And while this may create chaos and requires strict agreements between colleague, the feature itself is quite useful. Features like :dev, :test and :prod are quite prevalent in Common Lisp projects, and often they substitute other means of configuration and build type separation.

So, for the above reasons, and mainly for fun, I decided to hijack the new reader conditionals functionality to make it extensible and omnipresent.

Disclaimer: do not use this in your projects and do not think it is acceptable to do such things in real life. In fact, forget everything you're going to see here.

Read more ->>

Yesterday I needed to make a cheatsheet for my coworkers, but I didn't want to use online services or other proprietary tools. I turned to LaTeX, but there weren't any enticing eye-candy templates that I would be proud to give out. This template was the closest I could get, it looks neat by doesn't have a cherry on the top.

So I spent an evening to pimp that template and turn it into something that you can see below. Just edit the cheatsheet.tex file and compile it with xelatex.

TeX source

Resulting PDF

Read more ->>

A couple of years ago I have discovered this silly definition of the word Yegge on Urban Dictionary. For those who don't know Steve Yegge is a software developer, a former Google employee, and an author of his blog Stevey's Blog Rants. So the UD definition of "Yegge" goes as following:

A measurement of length of a piece of writing, particularly when indicating a length excessive for the genre. A Yegge is approximately 4000 words or 25 kilobytes.

Named for well known programmer and technical blogger Steve Yegge, whose blog up to about 2009 was notorious for entries of approximately 1 or 2 Yegges in length, vastly exceeding the typical length of blog entries in the genre.

Usage example: "I knew breaking up with him was a good idea after I got an email two Yegges long listing all the reasons why I should take him back."

Read more ->>

Quite often Clojure hackers need to interoperate with various Java classes. To do that they have to import those classes into the namespace. It is easy if you know the full name of the class, together with its package, but what if you don't? In that case you have to google where the sought class is located, and then type in the whole path to it.

Java developers who use any decent IDE are not familiar with such problem. They just type in the short name of the class, and the auto-completion offers them the list of all classes short name of which matches what they typed in. But can we have something like that for Clojure? Of course we can!

Read more ->>

Last summer I had to do a fair bit of Clojure compiler hacking. Since the primary objective of a compiler is to produce compiled code (in case of Clojure it is Java bytecode), this process involved reading classfiles every now and then. To make it easier I set up a nice environment using publicly available tools to make reading the bytecode as painless as possible.

Note that despite me using this workflow for Clojure, there is nothing here specific to it, so you can utilize the same setup when working with Java, Scala or any other JVM-compiled language out there.

Read more ->>

Burt Gummer

Emacs is the editor for real folk, and CIDER is one sweet piece of software to program in Clojure, but some would argue that it lacks "big IDE" refactoring tools. This is partly true, but not entirely. Today I gonna show you an easy and cool way to rename all references inside a single function. This can be useful if you want to rename a local variable, or a binding introduced by let.

There are certain tools that allow you to do project-wide replacement too, but they are outside the scope of its post. You should absolutely check @bbatsov's excellent Projectile package for some leads. But let's get back to our original task.

Read more ->>

A few weeks ago Cognitect ran the annual State of Clojure Survey, and presented the results, shortly followed by the analysis. While they did a great job on presenting and analyzing the choice answers, text responses were largely dismissed. Each year text responses contain the most information about which features users lack, or what are their biggest gripes with the language; so to avoid the survey being just another reason to feel good about Clojure, these should be analyzed too. It is easy to overlook a problem people are having if it is stated in stone-cold percentage. The other thing is when you read the sincere words of real people.

I understand that manual digging through 2000 textual responses is a hard and thankless job, but a man's gotta do what a man's gotta do. I've spent the whole day, I've read them all, and boy oh boy do I have some information for you.

NB: I've processed only answers related to Clojure, as I'm not into ClojureScript yet. If you want to do the same for CLJS, be my guest. Especially since CLJS has fewer answers.

NB: Great thanks to Alex Miller and Justin Gehtland for running the survey and providing the results.

Read more ->>

For more posts see the Archives page.