Skip to content

Commit

Permalink
A blog entry about requiring all available namespaces.
Browse files Browse the repository at this point in the history
  • Loading branch information
john committed Feb 8, 2010
1 parent 1bb9adf commit 5e37398
Showing 1 changed file with 79 additions and 0 deletions.
79 changes: 79 additions & 0 deletions require-all.clj
@@ -0,0 +1,79 @@
;; It often irritates me that I can't use clojure's built in documentation unless I've already
;; loaded the library I need.

;; Sometimes it turns out that the generic-looking function I need already exists, but it can be
;; hard to find it. Sometimes I can remember the function I want, but not its precise name or
;; library namespace.

;; It's also often the case that the best way to understand a function is to read the source.

;; The other day it occurred to me that a function to find all the namespaces available on the
;; classpath might help quite a bit, and I started to write one. And at that point I had the obvious
;; recursive thought.

;; Seek and ye shall find. Thank you Stuart Sierra.
(use 'clojure.contrib.find-namespaces)

;; First let's see what our classpath is:
(println "Classpath")
(doseq [p (seq (.getURLs (java.lang.ClassLoader/getSystemClassLoader)))] (println (str p)))

;; In my case, that's the clojure.jar and clojure.contrib.jar files, and also the directory
;; containing the files for swank-clojure, the library which allows it to talk to emacs.
(println "Swank namespaces")
(println (for [s (for [n (all-ns)] (name (ns-name n))) :when (. s contains "swank")] s))

;; Because I'm still a beginner, and not brave enough to modify swank, I'm more interested in
;; the namespaces provided by clojure and clojure.contrib

;; So far, the following have managed to get themselves loaded:
(println "None-swank namespaces")
(use 'clojure.contrib.pprint)
(pprint (sort (for [s (for [n (all-ns)] (name (ns-name n))) :when (not (. s contains "swank"))] s)))

;; But the following are in fact available
(pprint (find-namespaces-on-classpath))

;; Again, let's ignore the swank-related ones.
(pprint (filter #(not (. (str %) startsWith "swank")) (find-namespaces-on-classpath)))

;;For me there are only namespaces starting with either swank or clojure, because I don't have much
;;of a classpath. But it's easy enough to check that.
(defn find-namespaces-starting-with [strng]
(filter #(. (str %) startsWith strng) (find-namespaces-on-classpath)))

(map count (map find-namespaces-starting-with '("clojure" "swank" ""))) ; should add up

;; Some of the clojure.contrib libraries fail to load for me, so we have to bullet-proof require
(defn require-may-fail [ns]
(try
(print "Attempting to require " ns ": ")
(require ns)
(println "success")
(catch Exception e (println "couldn't require " ns "\nException\n" e "\n\n"))))

;; Now we can load everything
(doall (map require-may-fail (filter #(. (str %) startsWith "clojure") (find-namespaces-on-classpath))))

;; Now we have lots and lots of namespaces available: The number of 'batteries included' is impressive.
(println "None-swank namespaces")
(pprint (sort (for [s (for [n (all-ns)] (name (ns-name n))) :when (not (. s contains "swank"))] s)))

;; And the find-doc, doc, and source commands become really useful
;; Of course we not only have to find source, we actually can, now.
(find-doc "source code")

;; Also note that all this requiring hasn't brought any new functions into play yet.
;; To use something without qualification, you need to refer as well.
(refer 'clojure.contrib.repl-utils)
(doc source)
(source source)
(source get-source)
(:file (meta (resolve 'source)))


;; Other sources of enjoyment are the find and grep commands, and browsing clojure.contrib.jar and
;; clojure.jar These work particularly nicely under emacs. A good arrangement of find and grep is
;; (assuming that your clojure sources are under ~/opt):

;; find ~/opt/ -name "*.clj" -and -type f -print0 | xargs -0 -e grep -nH -e "repl-util"

0 comments on commit 5e37398

Please sign in to comment.