My favorite feature in leiningen 2

Wed 21 March 2012
  • 装备 tags:
  • clojure
  • leiningen
  • maven published: true comments: true

Recently, the leiningen team has released a preview version for leiningen 2. It brings new features to the clojure build tool. But my favorite one is not listed in any document. So I would like to share with you here.

As you know, leiningen is a project oriented tool. It manages dependencies for a particular project. In Java world, Maven and Gradle are also working in this manner.

In contrast, there are tools which manages dependencies in a system scope. For instance, pip(python), npm(nodejs) and gems(ruby). One advantage of these tools is easy for evaluating a library. Concretely, when you want to test pyclj, just run "pip install pyclj" to install it. Then open a REPL and type "import pyclj". That's pretty easy.

But in clojure/leiningen, to take a tutorial of "core.logic", we have following steps:

  1. Find a right directory and type "lein new logic-abc" to create a project.
  2. cd into it, edit project.clj, add core.logic as a dependency
  3. Run `lein deps`
  4. Start a REPL and follow the tutorial

So I guest you must have a lot of empty projects created for such purpose.

Now we could say goodbye to this situation. Leiningen 2 has move its dependency management core to a new library, called pomegranate. Pomegranate wraps aether, which is a maven library created by sonatype. With pomegranate, we can add a maven artifact from repository to REPL classpath. Still on the core.logic example, it becomes much easier:

[cc lang="clojure"]
$ lein2 repl
Welcome to REPL-y!
Clojure 1.3.0
Exit: Control+D or (exit) or (quit)
Commands: (help)
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
(sourcery function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Examples from clojuredocs.org:
(clojuredocs name-here)
(clojuredocs "ns-here" "name-here")
nil
user=> (use '[cemerick.pomegranate :only (add-dependencies)])
nil
user=> (add-dependencies :coordinates '[[org.clojure/core.logic "0.6.8"]])
{[org.clojure/clojure "1.3.0"] nil, [org.clojure/core.logic "0.6.8"] #{[org.clojure/clojure "1.3.0"]}}
user=> (use '[clojure.core.logic])
nilWARNING: == already refers to: #'clojure.core/== in namespace: user, being replaced by: #'clojure.core.logic/==
user=> (run* [q] (== q 1))
(1)
[/cc]

Now core.logic is right on you classpath and you are ready to use any functions under the namespace. There's no need to create project, no need to care about where the jars stored. Just start a REPL at anywhere you want. When you finished, send EOF to the REPL. Nothing to clean up.

My jython dependency manager jip has similar feature as I described above. It does great help to me. So I have been waiting for this feature in leiningen for a long time. Thanks to leiningen guys, it finally comes.

Edit 20120323 21:39

If you want to load libraries from clojars, you should explicitly add clojars in add-dependencies:
[cc lang="clojure"]
(add-dependencies :coordinates '[[incanter "1.2.3"]]
:repositories (merge cemerick.pomegranate.aether/maven-central
{"clojars" "http://clojars.org/repo"}))
[/cc]
(The example is copied from Pomegranate document.)