diff 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
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/clojure/contrib/macros.clj	Sat Aug 21 06:25:44 2010 -0400
     1.3 @@ -0,0 +1,84 @@
     1.4 +;; Various useful macros
     1.5 +;;
     1.6 +;; Everybody is invited to add their own little macros here!
     1.7 +;;
     1.8 +;; The use and distribution terms for this software are covered by the
     1.9 +;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
    1.10 +;; which can be found in the file epl-v10.html at the root of this
    1.11 +;; distribution. By using this software in any fashion, you are
    1.12 +;; agreeing to be bound by the terms of this license. You must not
    1.13 +;; remove this notice, or any other, from this software.
    1.14 +
    1.15 +(ns
    1.16 +  ^{:author "Konrad Hinsen"
    1.17 +     :doc "Various small macros"}
    1.18 +  clojure.contrib.macros)
    1.19 +
    1.20 +;; By Konrad Hinsen
    1.21 +(defmacro const
    1.22 +  "Evaluate the constant expression expr at compile time."
    1.23 +  [expr]
    1.24 +  (eval expr))
    1.25 +
    1.26 +;; By Konrad Hinsen
    1.27 +; This macro is made obsolete by Clojure's built-in letfn. I renamed it to
    1.28 +; letfn- (to avoid a name clash) but leave it in for a while, since its
    1.29 +; syntax is not quite the same as Clojure's. Expect this to disappear
    1.30 +; in the long run!
    1.31 +(defmacro letfn-
    1.32 +  "OBSOLETE: use clojure.core/letfn
    1.33 +   A variant of let for local function definitions. fn-bindings consists
    1.34 +   of name/args/body triples, with (letfn [name args body] ...)
    1.35 +   being equivalent to (let [name (fn name args body)] ...)."
    1.36 +  [fn-bindings & exprs]
    1.37 +  (let [makefn (fn [[name args body]] (list name (list 'fn name args body)))
    1.38 +	fns (vec (apply concat (map makefn (partition 3 fn-bindings))))]
    1.39 +  `(let ~fns ~@exprs)))
    1.40 +
    1.41 + ;; By Konrad Hinsen
    1.42 +
    1.43 + (defn- unqualified-symbol
    1.44 +  [s]
    1.45 +  (let [s-str (str s)]
    1.46 +    (symbol (subs s-str (inc (.indexOf s-str (int \/)))))))
    1.47 + 
    1.48 +(defn- bound-var?
    1.49 +  [var]
    1.50 +  (try
    1.51 +    (do (deref var) true)
    1.52 +    (catch java.lang.IllegalStateException e false)))
    1.53 +
    1.54 +(defn- fns-from-ns
    1.55 +  [ns ns-symbol]
    1.56 +  (apply concat
    1.57 +    (for [[k v] (ns-publics ns)
    1.58 +          :when (and (bound-var? v)
    1.59 +                     (fn? @v)
    1.60 +                     (not (:macro (meta v))))]
    1.61 +       [k (symbol (str ns-symbol) (str k))])))
    1.62 +
    1.63 +(defn- expand-symbol
    1.64 +  [ns-or-var-sym]
    1.65 +  (if (= ns-or-var-sym '*ns*)
    1.66 +    (fns-from-ns *ns* (ns-name *ns*))
    1.67 +    (if-let [ns (find-ns ns-or-var-sym)]
    1.68 +      (fns-from-ns ns ns-or-var-sym)
    1.69 +      (list (unqualified-symbol ns-or-var-sym) ns-or-var-sym))))
    1.70 +
    1.71 +(defmacro with-direct-linking
    1.72 +  "EXPERIMENTAL!
    1.73 +   Compiles the functions in body with direct links to the functions
    1.74 +   named in symbols, i.e. without a var lookup for each invocation.
    1.75 +   Symbols is a vector of symbols that name either vars or namespaces.
    1.76 +   A namespace reference is replaced by the list of all symbols in the
    1.77 +   namespace that are bound to functions. If symbols is not provided,
    1.78 +   the default value ['clojure.core] is used. The symbol *ns* can be
    1.79 +   used to refer to the current namespace."
    1.80 +  {:arglists '([symbols? & body])}
    1.81 +  [& body]
    1.82 +  (let [[symbols body] (if (vector? (first body))
    1.83 +                         [(first body) (rest body)]
    1.84 +                         [['clojure.core] body])
    1.85 +  			bindings (vec (mapcat expand-symbol symbols))]
    1.86 +    `(let ~bindings ~@body)))
    1.87 + 
    1.88 \ No newline at end of file