7

I used to like to include all of clojure.contrib, and require all the libraries. This makes find-doc useful as a discovery tool.

Nowadays (clojure 1.4) clojure.contrib is split into many sub-libraries. And that rather spoils my scheme, and it also means that I am constantly having to restart the JVM every time I need a new library.

So I'm busy constructing a project.clj file with many lines:

[org.clojure/algo.generic "0.0.6"]
....
[org.clojure/data.xml "0.0.4"]
....

So that I can get leiningen to put every clojure contrib library on the classpath, whether I need them or not.

And I reckon that this is going to be a spectacular pain in the neck, what with the version numbers, and all.

And I wonder if anyone has a better way to do the same thing?

EDIT: Thinking about it, if there's a web page somewhere that has a list of library names and current versions, I can turn that into a project file fairly easily.

Charles
  • 50,943
  • 13
  • 104
  • 142
John Lawrence Aspden
  • 17,124
  • 11
  • 67
  • 110

2 Answers2

8

You could use pomegranate if you just want to run it in the REPL (which seems like it would be the only appropriate use case, right?). You can have it look up the latest versions using the Maven Central API. I think this is better than maintaining some sort of dependencies project, generated or otherwise.

(require '[cemerick.pomegranate :refer [add-dependencies]])

(add-dependencies
  :coordinates '[[clj-http "0.5.8"]]
  :repositories {"clojars" "http://clojars.org/repo"})

(require '[clj-http.client :as client])

;; contrib project names from https://github.com/clojure
(def contrib ["tools.nrepl" "tools.trace" "tools.namespace" "tools.macro"
              "test.generative" "math.numeric-tower" "core.match" "core.logic"
              "data.priority-map" "core.contracts" "tools.cli" "java.jmx"
              "java.jdbc" "java.classpath" "data.xml" "data.json" "core.unify"
              "core.incubator" "core.cache" "algo.monads" "data.generators"
              "core.memoize" "math.combinatorics" "java.data" "tools.logging"
              "data.zip" "data.csv" "algo.generic" "data.codec"
              "data.finger-tree"])

(defn add-contrib-dependencies
  "look up the latest version of every contrib project in maven central,
   and add them as dependencies using pomegranate."
  [project-names]
  (add-dependencies
   :coordinates
   (map (juxt
         (comp symbol (partial format "org.clojure/%s"))
         (fn [proj]
             (Thread/sleep 100)
             (-> "http://search.maven.org/solrsearch/select?q=%s&rows=1&wt=json"
                 (format proj)
                 (client/get {:as :json})
                 :body :response :docs first :latestVersion)))
        project-names)))

Now you can just invoke this function on the list of project names:

user=> (add-contrib-dependencies contrib)
{[org.clojure/data.zip "0.1.1"] nil,
 [org.clojure/java.classpath "0.2.0"] nil,
 [org.clojure/core.cache "0.6.2"] nil, ...}

UPDATE: as suggested earlier, I had made this answer into a library. It can be used either as nREPL middleware or invoked manually from a running REPL session. The code can be found at https://github.com/rplevy/contrib-repl, where usage instructions can also be found.

rplevy
  • 5,393
  • 3
  • 32
  • 31
  • My God! I didn't even realise that this was possible in principle and you give me working code that does it. I'd normally blog about this (http://www.learningclojure.com) but it's clearly your idea so I'll leave it to you if you'd prefer. Can you let me know if you write it up so I can link to your write up? Or if you don't want to then can I? – John Lawrence Aspden Dec 03 '12 at 12:34
  • Also, I think you should make this into a project on clojars. If you don't want to then do you mind if I do? – John Lawrence Aspden Dec 03 '12 at 12:42
  • Thanks, John! I had fun answering this question and coming up with a solution. :) – rplevy Dec 03 '12 at 15:03
  • 1
    I wouldn't mind creating and maintaining this as a project. I'll try to get to it later today. – rplevy Dec 03 '12 at 15:07
  • 1
    Will do, let me know! In the meantime I'm already finding it very useful, especially as I'm using lein 2, so pomegranate is always there if I need it. Thanks. – John Lawrence Aspden Dec 03 '12 at 18:25
1

I feel your pain. It should be helpful http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go

sheldonh
  • 2,684
  • 24
  • 31
mobyte
  • 3,752
  • 1
  • 18
  • 16