view src/clojure/contrib/def.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 source
1 ;; Copyright (c) Stephen C. Gilardi. All rights reserved. The use and
2 ;; distribution terms for this software are covered by the Eclipse Public
3 ;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can
4 ;; be found in the file epl-v10.html at the root of this distribution. By
5 ;; using this software in any fashion, you are agreeing to be bound by the
6 ;; terms of this license. You must not remove this notice, or any other,
7 ;; from this software.
8 ;;
9 ;; File: def.clj
10 ;;
11 ;; def.clj provides variants of def that make including doc strings and
12 ;; making private definitions more succinct.
13 ;;
14 ;; scgilardi (gmail)
15 ;; 17 May 2008
17 (ns
18 ^{:author "Stephen C. Gilardi",
19 :doc "def.clj provides variants of def that make including doc strings and
20 making private definitions more succinct."}
21 clojure.contrib.def)
23 (defmacro defvar
24 "Defines a var with an optional intializer and doc string"
25 ([name]
26 (list `def name))
27 ([name init]
28 (list `def name init))
29 ([name init doc]
30 (list `def (with-meta name (assoc (meta name) :doc doc)) init)))
32 (defmacro defunbound
33 "Defines an unbound var with optional doc string"
34 ([name]
35 (list `def name))
36 ([name doc]
37 (list `def (with-meta name (assoc (meta name) :doc doc)))))
39 (defmacro defmacro-
40 "Same as defmacro but yields a private definition"
41 [name & decls]
42 (list* `defmacro (with-meta name (assoc (meta name) :private true)) decls))
44 (defmacro defvar-
45 "Same as defvar but yields a private definition"
46 [name & decls]
47 (list* `defvar (with-meta name (assoc (meta name) :private true)) decls))
49 (defmacro defunbound-
50 "Same as defunbound but yields a private definition"
51 [name & decls]
52 (list* `defunbound (with-meta name (assoc (meta name) :private true)) decls))
54 (defmacro defstruct-
55 "Same as defstruct but yields a private definition"
56 [name & decls]
57 (list* `defstruct (with-meta name (assoc (meta name) :private true)) decls))
59 (defmacro defonce-
60 "Same as defonce but yields a private definition"
61 ([name expr]
62 (list `defonce (with-meta name (assoc (meta name) :private true)) expr))
63 ([name expr doc]
64 (list `defonce (with-meta name (assoc (meta name) :private true :doc doc)) expr)))
66 (defmacro defalias
67 "Defines an alias for a var: a new var with the same root binding (if
68 any) and similar metadata. The metadata of the alias is its initial
69 metadata (as provided by def) merged into the metadata of the original."
70 ([name orig]
71 `(do
72 (alter-meta!
73 (if (.hasRoot (var ~orig))
74 (def ~name (.getRoot (var ~orig)))
75 (def ~name))
76 ;; When copying metadata, disregard {:macro false}.
77 ;; Workaround for http://www.assembla.com/spaces/clojure/tickets/273
78 #(conj (dissoc % :macro)
79 (apply dissoc (meta (var ~orig)) (remove #{:macro} (keys %)))))
80 (var ~name)))
81 ([name orig doc]
82 (list `defalias (with-meta name (assoc (meta name) :doc doc)) orig)))
84 ; defhinted by Chouser:
85 (defmacro defhinted
86 "Defines a var with a type hint matching the class of the given
87 init. Be careful about using any form of 'def' or 'binding' to a
88 value of a different type. See http://paste.lisp.org/display/73344"
89 [sym init]
90 `(do
91 (def ~sym ~init)
92 (alter-meta! (var ~sym) assoc :tag (class ~sym))
93 (var ~sym)))
95 ; name-with-attributes by Konrad Hinsen:
96 (defn name-with-attributes
97 "To be used in macro definitions.
98 Handles optional docstrings and attribute maps for a name to be defined
99 in a list of macro arguments. If the first macro argument is a string,
100 it is added as a docstring to name and removed from the macro argument
101 list. If afterwards the first macro argument is a map, its entries are
102 added to the name's metadata map and the map is removed from the
103 macro argument list. The return value is a vector containing the name
104 with its extended metadata map and the list of unprocessed macro
105 arguments."
106 [name macro-args]
107 (let [[docstring macro-args] (if (string? (first macro-args))
108 [(first macro-args) (next macro-args)]
109 [nil macro-args])
110 [attr macro-args] (if (map? (first macro-args))
111 [(first macro-args) (next macro-args)]
112 [{} macro-args])
113 attr (if docstring
114 (assoc attr :doc docstring)
115 attr)
116 attr (if (meta name)
117 (conj (meta name) attr)
118 attr)]
119 [(with-meta name attr) macro-args]))
121 ; defnk by Meikel Brandmeyer:
122 (defmacro defnk
123 "Define a function accepting keyword arguments. Symbols up to the first
124 keyword in the parameter list are taken as positional arguments. Then
125 an alternating sequence of keywords and defaults values is expected. The
126 values of the keyword arguments are available in the function body by
127 virtue of the symbol corresponding to the keyword (cf. :keys destructuring).
128 defnk accepts an optional docstring as well as an optional metadata map."
129 [fn-name & fn-tail]
130 (let [[fn-name [args & body]] (name-with-attributes fn-name fn-tail)
131 [pos kw-vals] (split-with symbol? args)
132 syms (map #(-> % name symbol) (take-nth 2 kw-vals))
133 values (take-nth 2 (rest kw-vals))
134 sym-vals (apply hash-map (interleave syms values))
135 de-map {:keys (vec syms)
136 :or sym-vals}]
137 `(defn ~fn-name
138 [~@pos & options#]
139 (let [~de-map (apply hash-map options#)]
140 ~@body))))
142 ; defn-memo by Chouser:
143 (defmacro defn-memo
144 "Just like defn, but memoizes the function using clojure.core/memoize"
145 [fn-name & defn-stuff]
146 `(do
147 (defn ~fn-name ~@defn-stuff)
148 (alter-var-root (var ~fn-name) memoize)
149 (var ~fn-name)))