I finally managed to polish a thing that lived on my hard drive in disassembled state for years. ns-graph is initially a fork of the abandoned clojure-dependency-grapher. As vain as it may seem, this tools is often very useful to me. It is surprisingly descriptive when you need to understand the high-level architecture of some project. Recently I wanted to catch up with the changes in cider-nrepl and figure out where exactly it uses its new dependencies. Well, sometimes you should think carefully what you wish for.
Imagine the following setup: service A serves a stream of data items by exposing the latest batch of these items as an HTTP endpoint. Application B polls service A every now and then, fetches the recent batch and puts the unwrapped items onto a core.async channel. The consumer(s) on the other side of the channel may come and go. The nature of the data is also such that it is droppable (not every item has to be processed) and becomes stale over time.
If you don't know yet what a transducer is, or how they work, there are two amazing talks to get started, both by Rich Hickey: Transducers and Inside Transducers. I watched those talks a couple of times each, and I moderately use transducers in my projects; thus I have a decent understanding of transducers. Or so I thought.
Yesterday my coworker and I delved into reading the already implemented
transducers in clojure.core, and started pondering why some seq-operating
functions don't have a transducer counterpart. Multiple-collection
Probably missing because it doesn't fit the single-stream semantic very well.
drop-last? Those two can actually be implemented as
transducers by using a queue. And then…
cycle? Can we do cycle?
As it turned out, my knowledge of transducers was limited. I could use them, and
I got the idea behind them, but until I implemented one I lacked the perception
of the underlying machinery. Today I will guide you step by step through how we
cycle transducer, so you might also get a better comprehension of
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
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
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.
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.
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
(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* ['cider.nrepl/cider-middleware 'refactor-nrepl.middleware/wrap-refactor]))
Then in Emacs do
M-x customize-variable cider-boot-parameters and set it to
cider repl -s wait.
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
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
: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.
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
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."
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!
For more posts see the Archives page.