Mercurial > lasercutter
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/clojure/contrib/def.clj Sat Aug 21 06:25:44 2010 -0400 1.3 @@ -0,0 +1,149 @@ 1.4 +;; Copyright (c) Stephen C. Gilardi. All rights reserved. The use and 1.5 +;; distribution terms for this software are covered by the Eclipse Public 1.6 +;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can 1.7 +;; be found in the file epl-v10.html at the root of this distribution. By 1.8 +;; using this software in any fashion, you are agreeing to be bound by the 1.9 +;; terms of this license. You must not remove this notice, or any other, 1.10 +;; from this software. 1.11 +;; 1.12 +;; File: def.clj 1.13 +;; 1.14 +;; def.clj provides variants of def that make including doc strings and 1.15 +;; making private definitions more succinct. 1.16 +;; 1.17 +;; scgilardi (gmail) 1.18 +;; 17 May 2008 1.19 + 1.20 +(ns 1.21 + ^{:author "Stephen C. Gilardi", 1.22 + :doc "def.clj provides variants of def that make including doc strings and 1.23 +making private definitions more succinct."} 1.24 + clojure.contrib.def) 1.25 + 1.26 +(defmacro defvar 1.27 + "Defines a var with an optional intializer and doc string" 1.28 + ([name] 1.29 + (list `def name)) 1.30 + ([name init] 1.31 + (list `def name init)) 1.32 + ([name init doc] 1.33 + (list `def (with-meta name (assoc (meta name) :doc doc)) init))) 1.34 + 1.35 +(defmacro defunbound 1.36 + "Defines an unbound var with optional doc string" 1.37 + ([name] 1.38 + (list `def name)) 1.39 + ([name doc] 1.40 + (list `def (with-meta name (assoc (meta name) :doc doc))))) 1.41 + 1.42 +(defmacro defmacro- 1.43 + "Same as defmacro but yields a private definition" 1.44 + [name & decls] 1.45 + (list* `defmacro (with-meta name (assoc (meta name) :private true)) decls)) 1.46 + 1.47 +(defmacro defvar- 1.48 + "Same as defvar but yields a private definition" 1.49 + [name & decls] 1.50 + (list* `defvar (with-meta name (assoc (meta name) :private true)) decls)) 1.51 + 1.52 +(defmacro defunbound- 1.53 + "Same as defunbound but yields a private definition" 1.54 + [name & decls] 1.55 + (list* `defunbound (with-meta name (assoc (meta name) :private true)) decls)) 1.56 + 1.57 +(defmacro defstruct- 1.58 + "Same as defstruct but yields a private definition" 1.59 + [name & decls] 1.60 + (list* `defstruct (with-meta name (assoc (meta name) :private true)) decls)) 1.61 + 1.62 +(defmacro defonce- 1.63 + "Same as defonce but yields a private definition" 1.64 + ([name expr] 1.65 + (list `defonce (with-meta name (assoc (meta name) :private true)) expr)) 1.66 + ([name expr doc] 1.67 + (list `defonce (with-meta name (assoc (meta name) :private true :doc doc)) expr))) 1.68 + 1.69 +(defmacro defalias 1.70 + "Defines an alias for a var: a new var with the same root binding (if 1.71 + any) and similar metadata. The metadata of the alias is its initial 1.72 + metadata (as provided by def) merged into the metadata of the original." 1.73 + ([name orig] 1.74 + `(do 1.75 + (alter-meta! 1.76 + (if (.hasRoot (var ~orig)) 1.77 + (def ~name (.getRoot (var ~orig))) 1.78 + (def ~name)) 1.79 + ;; When copying metadata, disregard {:macro false}. 1.80 + ;; Workaround for http://www.assembla.com/spaces/clojure/tickets/273 1.81 + #(conj (dissoc % :macro) 1.82 + (apply dissoc (meta (var ~orig)) (remove #{:macro} (keys %))))) 1.83 + (var ~name))) 1.84 + ([name orig doc] 1.85 + (list `defalias (with-meta name (assoc (meta name) :doc doc)) orig))) 1.86 + 1.87 +; defhinted by Chouser: 1.88 +(defmacro defhinted 1.89 + "Defines a var with a type hint matching the class of the given 1.90 + init. Be careful about using any form of 'def' or 'binding' to a 1.91 + value of a different type. See http://paste.lisp.org/display/73344" 1.92 + [sym init] 1.93 + `(do 1.94 + (def ~sym ~init) 1.95 + (alter-meta! (var ~sym) assoc :tag (class ~sym)) 1.96 + (var ~sym))) 1.97 + 1.98 +; name-with-attributes by Konrad Hinsen: 1.99 +(defn name-with-attributes 1.100 + "To be used in macro definitions. 1.101 + Handles optional docstrings and attribute maps for a name to be defined 1.102 + in a list of macro arguments. If the first macro argument is a string, 1.103 + it is added as a docstring to name and removed from the macro argument 1.104 + list. If afterwards the first macro argument is a map, its entries are 1.105 + added to the name's metadata map and the map is removed from the 1.106 + macro argument list. The return value is a vector containing the name 1.107 + with its extended metadata map and the list of unprocessed macro 1.108 + arguments." 1.109 + [name macro-args] 1.110 + (let [[docstring macro-args] (if (string? (first macro-args)) 1.111 + [(first macro-args) (next macro-args)] 1.112 + [nil macro-args]) 1.113 + [attr macro-args] (if (map? (first macro-args)) 1.114 + [(first macro-args) (next macro-args)] 1.115 + [{} macro-args]) 1.116 + attr (if docstring 1.117 + (assoc attr :doc docstring) 1.118 + attr) 1.119 + attr (if (meta name) 1.120 + (conj (meta name) attr) 1.121 + attr)] 1.122 + [(with-meta name attr) macro-args])) 1.123 + 1.124 +; defnk by Meikel Brandmeyer: 1.125 +(defmacro defnk 1.126 + "Define a function accepting keyword arguments. Symbols up to the first 1.127 + keyword in the parameter list are taken as positional arguments. Then 1.128 + an alternating sequence of keywords and defaults values is expected. The 1.129 + values of the keyword arguments are available in the function body by 1.130 + virtue of the symbol corresponding to the keyword (cf. :keys destructuring). 1.131 + defnk accepts an optional docstring as well as an optional metadata map." 1.132 + [fn-name & fn-tail] 1.133 + (let [[fn-name [args & body]] (name-with-attributes fn-name fn-tail) 1.134 + [pos kw-vals] (split-with symbol? args) 1.135 + syms (map #(-> % name symbol) (take-nth 2 kw-vals)) 1.136 + values (take-nth 2 (rest kw-vals)) 1.137 + sym-vals (apply hash-map (interleave syms values)) 1.138 + de-map {:keys (vec syms) 1.139 + :or sym-vals}] 1.140 + `(defn ~fn-name 1.141 + [~@pos & options#] 1.142 + (let [~de-map (apply hash-map options#)] 1.143 + ~@body)))) 1.144 + 1.145 +; defn-memo by Chouser: 1.146 +(defmacro defn-memo 1.147 + "Just like defn, but memoizes the function using clojure.core/memoize" 1.148 + [fn-name & defn-stuff] 1.149 + `(do 1.150 + (defn ~fn-name ~@defn-stuff) 1.151 + (alter-var-root (var ~fn-name) memoize) 1.152 + (var ~fn-name)))