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