Dear Clojurians, I found the following procedure quite useful when including Tom Faulhaber's cl-format in VimClojure.
I didn't want to depend on it, so I decided to provide the functionality optionally: if the cl-format.jar is available use it, otherwise use some sensible default. The following layout is used by Chouser in clojure.contrib but should deserve some more spotlight. To include the functionality I started with providing some facade which also implements the defaults (defn pretty-print"Print the given form in a pretty way. If Tom Faulhaber's pretty printer is
not installed simply defaults prn." [form] (prn form)) (defn pretty-print-code"Print the given form in a pretty way. If Tom Faulhaber's pretty printer is not installed simply defaults prn. Uses the *code-dispatch* formatting."
[form]
(prn form))
These functions are pretty straight forward. They
provide the interface used in VimClojure and default
to prn.
Now we have to load the cl-format library. The problem
is, that if the library is not available this will throw an
exception at compile time. So wrapping the require
in try will not help. Here comes Chouser's trick: put the
require in another file and load this file. Using this
technique we can simply catch the Exception, check
with some Voodoo heuristic whether it was because
of the missing jar and re-throw otherwise.
(try
(load "optional/cl-format")
(catch Exception exc
(when-not (re-find #"com/infolace/format__init" (str exc))
(throw exc))))
In the optional/cl-format.clj file, we finally interface to
the optional library. We require the library and replace
the facade functions we defined before.
(require '[com.infolace.format :as cl-format])
(defoptional pretty-print
[form]
(cl-format/pprint form))
(defoptional pretty-print-code
[form]
(cl-format/with-pprint-dispatch cl-format/*code-dispatch*
(cl-format/pprint form)))
To save some work I defined a small helper macro,
which transfers the docstring from the default
implementation to the re-definition.
(defmacro defoptional
[sym args & body]
`(let [docstring# (:doc (meta (var ~sym)))]
(defn ~sym ~args ~...@body)
(alter-meta! (var ~sym) assoc :doc docstring#)))
Now we have a completely optional dependency
on an external library. In case it's there, it will be
used. Otherwise the system falls back transparently
to the default implementation.
Maybe you find this useful.
Sincerely
Meikel
smime.p7s
Description: S/MIME cryptographic signature
