annotate src/clojure/contrib/macros.clj @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
rev   line source
rlm@10 1 ;; Various useful macros
rlm@10 2 ;;
rlm@10 3 ;; Everybody is invited to add their own little macros here!
rlm@10 4 ;;
rlm@10 5 ;; The use and distribution terms for this software are covered by the
rlm@10 6 ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
rlm@10 7 ;; which can be found in the file epl-v10.html at the root of this
rlm@10 8 ;; distribution. By using this software in any fashion, you are
rlm@10 9 ;; agreeing to be bound by the terms of this license. You must not
rlm@10 10 ;; remove this notice, or any other, from this software.
rlm@10 11
rlm@10 12 (ns
rlm@10 13 ^{:author "Konrad Hinsen"
rlm@10 14 :doc "Various small macros"}
rlm@10 15 clojure.contrib.macros)
rlm@10 16
rlm@10 17 ;; By Konrad Hinsen
rlm@10 18 (defmacro const
rlm@10 19 "Evaluate the constant expression expr at compile time."
rlm@10 20 [expr]
rlm@10 21 (eval expr))
rlm@10 22
rlm@10 23 ;; By Konrad Hinsen
rlm@10 24 ; This macro is made obsolete by Clojure's built-in letfn. I renamed it to
rlm@10 25 ; letfn- (to avoid a name clash) but leave it in for a while, since its
rlm@10 26 ; syntax is not quite the same as Clojure's. Expect this to disappear
rlm@10 27 ; in the long run!
rlm@10 28 (defmacro letfn-
rlm@10 29 "OBSOLETE: use clojure.core/letfn
rlm@10 30 A variant of let for local function definitions. fn-bindings consists
rlm@10 31 of name/args/body triples, with (letfn [name args body] ...)
rlm@10 32 being equivalent to (let [name (fn name args body)] ...)."
rlm@10 33 [fn-bindings & exprs]
rlm@10 34 (let [makefn (fn [[name args body]] (list name (list 'fn name args body)))
rlm@10 35 fns (vec (apply concat (map makefn (partition 3 fn-bindings))))]
rlm@10 36 `(let ~fns ~@exprs)))
rlm@10 37
rlm@10 38 ;; By Konrad Hinsen
rlm@10 39
rlm@10 40 (defn- unqualified-symbol
rlm@10 41 [s]
rlm@10 42 (let [s-str (str s)]
rlm@10 43 (symbol (subs s-str (inc (.indexOf s-str (int \/)))))))
rlm@10 44
rlm@10 45 (defn- bound-var?
rlm@10 46 [var]
rlm@10 47 (try
rlm@10 48 (do (deref var) true)
rlm@10 49 (catch java.lang.IllegalStateException e false)))
rlm@10 50
rlm@10 51 (defn- fns-from-ns
rlm@10 52 [ns ns-symbol]
rlm@10 53 (apply concat
rlm@10 54 (for [[k v] (ns-publics ns)
rlm@10 55 :when (and (bound-var? v)
rlm@10 56 (fn? @v)
rlm@10 57 (not (:macro (meta v))))]
rlm@10 58 [k (symbol (str ns-symbol) (str k))])))
rlm@10 59
rlm@10 60 (defn- expand-symbol
rlm@10 61 [ns-or-var-sym]
rlm@10 62 (if (= ns-or-var-sym '*ns*)
rlm@10 63 (fns-from-ns *ns* (ns-name *ns*))
rlm@10 64 (if-let [ns (find-ns ns-or-var-sym)]
rlm@10 65 (fns-from-ns ns ns-or-var-sym)
rlm@10 66 (list (unqualified-symbol ns-or-var-sym) ns-or-var-sym))))
rlm@10 67
rlm@10 68 (defmacro with-direct-linking
rlm@10 69 "EXPERIMENTAL!
rlm@10 70 Compiles the functions in body with direct links to the functions
rlm@10 71 named in symbols, i.e. without a var lookup for each invocation.
rlm@10 72 Symbols is a vector of symbols that name either vars or namespaces.
rlm@10 73 A namespace reference is replaced by the list of all symbols in the
rlm@10 74 namespace that are bound to functions. If symbols is not provided,
rlm@10 75 the default value ['clojure.core] is used. The symbol *ns* can be
rlm@10 76 used to refer to the current namespace."
rlm@10 77 {:arglists '([symbols? & body])}
rlm@10 78 [& body]
rlm@10 79 (let [[symbols body] (if (vector? (first body))
rlm@10 80 [(first body) (rest body)]
rlm@10 81 [['clojure.core] body])
rlm@10 82 bindings (vec (mapcat expand-symbol symbols))]
rlm@10 83 `(let ~bindings ~@body)))
rlm@10 84