Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 845 lines (738 sloc) 35.081 kb
5f090a09 » richhickey
2009-10-28 first cut at defclass/deftype
1 ; Copyright (c) Rich Hickey. All rights reserved.
2 ; The use and distribution terms for this software are covered by the
3 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 ; which can be found in the file epl-v10.html at the root of this distribution.
5 ; By using this software in any fashion, you are agreeing to be bound by
6 ; the terms of this license.
7 ; You must not remove this notice, or any other, from this software.
8
9 (in-ns 'clojure.core)
10
f612ecff » richhickey
2010-02-10 inlined bit shifts, added definterface (undocumented for now)
11 ;;;;;;;;;;;;;;;;;;;;;;;;;;;; definterface ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12
1f70ed92 » stuarthalloway
2010-04-23 munge package names in definterface, #306
13 (defn namespace-munge
14 "Convert a Clojure namespace name to a legal Java package name."
c1c39162 » stuarthalloway
2010-04-29 metadata for :added
15 {:added "1.2"}
1f70ed92 » stuarthalloway
2010-04-23 munge package names in definterface, #306
16 [ns]
17 (.replace (str ns) \- \_))
18
f612ecff » richhickey
2010-02-10 inlined bit shifts, added definterface (undocumented for now)
19 ;for now, built on gen-interface
4784f4c5 » tsdh
2012-10-20 Add docstring and :added metadata to definterface.
20 (defmacro definterface
21 "Creates a new Java interface with the given name and method sigs.
22 The method return types and parameter types may be specified with type hints,
23 defaulting to Object if omitted.
24
25 (definterface MyInterface
26 (^int method1 [x])
27 (^Bar method2 [^Baz b ^Quux q]))"
28 {:added "1.2"} ;; Present since 1.2, but made public in 1.5.
f612ecff » richhickey
2010-02-10 inlined bit shifts, added definterface (undocumented for now)
29 [name & sigs]
30 (let [tag (fn [x] (or (:tag (meta x)) Object))
31 psig (fn [[name [& args]]]
db3466e8 » richhickey
2010-04-26 support type and parameter annotations in definterface
32 (vector name (vec (map tag args)) (tag name) (map meta args)))
33 cname (with-meta (symbol (str (namespace-munge *ns*) "." name)) (meta name))]
2ac93197 » richhickey
2010-06-06 prevent dynamic classes from being flushed before use
34 `(let []
35 (gen-interface :name ~cname :methods ~(vec (map psig sigs)))
36 (import ~cname))))
f612ecff » richhickey
2010-02-10 inlined bit shifts, added definterface (undocumented for now)
37
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
38 ;;;;;;;;;;;;;;;;;;;;;;;;;;;; reify/deftype ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
39
40 (defn- parse-opts [s]
41 (loop [opts {} [k v & rs :as s] s]
42 (if (keyword? k)
43 (recur (assoc opts k v) rs)
44 [opts s])))
45
46 (defn- parse-impls [specs]
47 (loop [ret {} s specs]
48 (if (seq s)
49 (recur (assoc ret (first s) (take-while seq? (next s)))
50 (drop-while seq? (next s)))
51 ret)))
52
53 (defn- parse-opts+specs [opts+specs]
54 (let [[opts specs] (parse-opts opts+specs)
55 impls (parse-impls specs)
56 interfaces (-> (map #(if (var? (resolve %))
57 (:on (deref (resolve %)))
58 %)
59 (keys impls))
60 set
61 (disj 'Object 'java.lang.Object)
62 vec)
bf8bb79c » richhickey
2010-04-27 added parameter destructuring support to reify and deftype/record
63 methods (map (fn [[name params & body]]
64 (cons name (maybe-destructured params body)))
65 (apply concat (vals impls)))]
ba6cc3bd » richhickey
2010-04-02 reify/deftype methods now take target ('this') object as explicit fir…
66 (when-let [bad-opts (seq (remove #{:no-print} (keys opts)))]
67 (throw (IllegalArgumentException. (apply print-str "Unsupported option(s) -" bad-opts))))
f612ecff » richhickey
2010-02-10 inlined bit shifts, added definterface (undocumented for now)
68 [interfaces methods opts]))
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
69
a84a4e1f » richhickey
2009-11-30 deftype and reify support direct implementation of protocols
70 (defmacro reify
71 "reify is a macro with the following structure:
72
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
73 (reify options* specs*)
74
ba6cc3bd » richhickey
2010-04-02 reify/deftype methods now take target ('this') object as explicit fir…
75 Currently there are no options.
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
76
77 Each spec consists of the protocol or interface name followed by zero
78 or more method bodies:
79
80 protocol-or-interface-or-Object
befba000 » Fogus
2010-05-05 Fixes missing this arg on the reify and defprotocol docstrings #340
81 (methodName [args+] body)*
a84a4e1f » richhickey
2009-11-30 deftype and reify support direct implementation of protocols
82
83 Methods should be supplied for all methods of the desired
84 protocol(s) and interface(s). You can also define overrides for
befba000 » Fogus
2010-05-05 Fixes missing this arg on the reify and defprotocol docstrings #340
85 methods of Object. Note that the first parameter must be supplied to
ba6cc3bd » richhickey
2010-04-02 reify/deftype methods now take target ('this') object as explicit fir…
86 correspond to the target object ('this' in Java parlance). Thus
87 methods for interfaces will take one more argument than do the
88 interface declarations. Note also that recur calls to the method
89 head should *not* pass the target object, it will be supplied
90 automatically and can not be substituted.
a84a4e1f » richhickey
2009-11-30 deftype and reify support direct implementation of protocols
91
92 The return type can be indicated by a type hint on the method name,
93 and arg types can be indicated by a type hint on arg names. If you
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
94 leave out all hints, reify will try to match on same name/arity
a84a4e1f » richhickey
2009-11-30 deftype and reify support direct implementation of protocols
95 method in the protocol(s)/interface(s) - this is preferred. If you
96 supply any hints at all, no inference is done, so all hints (or
97 default of Object) must be correct, for both arguments and return
98 type. If a method is overloaded in a protocol/interface, multiple
99 independent method definitions must be supplied. If overloaded with
100 same arity in an interface you must specify complete hints to
101 disambiguate - a missing hint implies Object.
102
103 recur works to method heads The method bodies of reify are lexical
104 closures, and can refer to the surrounding local scope:
105
106 (str (let [f \"foo\"]
a3e95cf5 » richhickey
2009-12-04 update example in reify doc
107 (reify Object
befba000 » Fogus
2010-05-05 Fixes missing this arg on the reify and defprotocol docstrings #340
108 (toString [this] f))))
a84a4e1f » richhickey
2009-11-30 deftype and reify support direct implementation of protocols
109 == \"foo\"
110
111 (seq (let [f \"foo\"]
a3e95cf5 » richhickey
2009-12-04 update example in reify doc
112 (reify clojure.lang.Seqable
befba000 » Fogus
2010-05-05 Fixes missing this arg on the reify and defprotocol docstrings #340
113 (seq [this] (seq f)))))
9dd6c815 » kotarak
2011-08-25 Fix docstring of reify
114 == (\\f \\o \\o))
115
116 reify always implements clojure.lang.IObj and transfers meta
117 data of the form to the created object.
118
119 (meta ^{:k :v} (reify Object (toString [this] \"foo\")))
120 == {:k :v}"
c1c39162 » stuarthalloway
2010-04-29 metadata for :added
121 {:added "1.2"}
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
122 [& opts+specs]
123 (let [[interfaces methods] (parse-opts+specs opts+specs)]
67864eb0 » richhickey
2010-03-19 added IObj and metadata propagation support for reify, so #^{:my :met…
124 (with-meta `(reify* ~interfaces ~@methods) (meta &form))))
5f090a09 » richhickey
2009-10-28 first cut at defclass/deftype
125
126 (defn hash-combine [x y]
127 (clojure.lang.Util/hashCombine x (clojure.lang.Util/hash y)))
128
77173bbf » richhickey
2009-11-30 protocols gen interface of same name, e.g. my.ns/Protocol gens my.ns.…
129 (defn munge [s]
130 ((if (symbol? s) symbol str) (clojure.lang.Compiler/munge (str s))))
131
e0e0b6a2 » stuarthalloway
2010-04-23 make defrecord .cons work, #231
132 (defn- imap-cons
78793836 » richhickey
2010-04-26 replace #^s with ^s
133 [^IPersistentMap this o]
e0e0b6a2 » stuarthalloway
2010-04-23 make defrecord .cons work, #231
134 (cond
135 (instance? java.util.Map$Entry o)
78793836 » richhickey
2010-04-26 replace #^s with ^s
136 (let [^java.util.Map$Entry pair o]
e0e0b6a2 » stuarthalloway
2010-04-23 make defrecord .cons work, #231
137 (.assoc this (.getKey pair) (.getValue pair)))
138 (instance? clojure.lang.IPersistentVector o)
78793836 » richhickey
2010-04-26 replace #^s with ^s
139 (let [^clojure.lang.IPersistentVector vec o]
e0e0b6a2 » stuarthalloway
2010-04-23 make defrecord .cons work, #231
140 (.assoc this (.nth vec 0) (.nth vec 1)))
141 :else (loop [this this
142 o o]
143 (if (seq o)
78793836 » richhickey
2010-04-26 replace #^s with ^s
144 (let [^java.util.Map$Entry pair (first o)]
e0e0b6a2 » stuarthalloway
2010-04-23 make defrecord .cons work, #231
145 (recur (.assoc this (.getKey pair) (.getValue pair)) (rest o)))
146 this))))
147
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
148 (defn- emit-defrecord
149 "Do not use this directly - use defrecord"
c1c39162 » stuarthalloway
2010-04-29 metadata for :added
150 {:added "1.2"}
292836f8 » richhickey
2009-11-12 got rid of defclass. deftype now can refer to self-type, will emit sa…
151 [tagname name fields interfaces methods]
ca1d49a1 » stuarthalloway
2011-05-13 get rid of spurious tags on deftype/defrecord (again!)
152 (let [classname (with-meta (symbol (str (namespace-munge *ns*) "." name)) (meta name))
5f090a09 » richhickey
2009-10-28 first cut at defclass/deftype
153 interfaces (vec interfaces)
154 interface-set (set (map resolve interfaces))
155 methodname-set (set (map first methods))
a3d42748 » richhickey
2009-10-29 don't propagate field hints into method bodies
156 hinted-fields fields
157 fields (vec (map #(with-meta % nil) fields))
5f090a09 » richhickey
2009-10-28 first cut at defclass/deftype
158 base-fields fields
f75d47ef » brentonashworth
2012-04-21 CLJ-867: Records implement IHashEq to incorporate record name into ha…
159 fields (conj fields '__meta '__extmap)
160 type-hash (hash classname)]
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
161 (when (some #{:volatile-mutable :unsynchronized-mutable} (mapcat (comp keys meta) hinted-fields))
162 (throw (IllegalArgumentException. ":volatile-mutable or :unsynchronized-mutable not supported for record fields")))
c2b229e6 » khinsen
2010-05-28 Remove potential conflicts between field names and method argument na…
163 (let [gs (gensym)]
5f090a09 » richhickey
2009-10-28 first cut at defclass/deftype
164 (letfn
ac1e8ad9 » fogus
2011-05-10 Changes to support defrecord and deftype literals. See CLJ-374
165 [(irecord [[i m]]
166 [(conj i 'clojure.lang.IRecord)
167 m])
168 (eqhash [[i m]]
f75d47ef » brentonashworth
2012-04-21 CLJ-867: Records implement IHashEq to incorporate record name into ha…
169 [(conj i 'clojure.lang.IHashEq)
170 (conj m
6fd7b773 » cgrand
2012-11-27 make hasheq coherent with equiv for records
171 `(hasheq [this#] (bit-xor ~type-hash (clojure.lang.APersistentMap/mapHasheq this#)))
ac484ba4 » richhickey
2010-08-04 fix record equality with other maps, = includes type, .equals doesn't…
172 `(hashCode [this#] (clojure.lang.APersistentMap/mapHash this#))
173 `(equals [this# ~gs] (clojure.lang.APersistentMap/mapEquals this# ~gs)))])
5f090a09 » richhickey
2009-10-28 first cut at defclass/deftype
174 (iobj [[i m]]
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
175 [(conj i 'clojure.lang.IObj)
c2b229e6 » khinsen
2010-05-28 Remove potential conflicts between field names and method argument na…
176 (conj m `(meta [this#] ~'__meta)
177 `(withMeta [this# ~gs] (new ~tagname ~@(replace {'__meta gs} fields))))])
5f090a09 » richhickey
2009-10-28 first cut at defclass/deftype
178 (ilookup [[i m]]
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
179 [(conj i 'clojure.lang.ILookup 'clojure.lang.IKeywordLookup)
c2b229e6 » khinsen
2010-05-28 Remove potential conflicts between field names and method argument na…
180 (conj m `(valAt [this# k#] (.valAt this# k# nil))
181 `(valAt [this# k# else#]
182 (case k# ~@(mapcat (fn [fld] [(keyword fld) fld])
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
183 base-fields)
c2b229e6 » khinsen
2010-05-28 Remove potential conflicts between field names and method argument na…
184 (get ~'__extmap k# else#)))
185 `(getLookupThunk [this# k#]
186 (let [~'gclass (class this#)]
187 (case k#
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
188 ~@(let [hinted-target (with-meta 'gtarget {:tag tagname})]
189 (mapcat
190 (fn [fld]
595d0f7a » Michael Fogus and Alan Dipert
2011-11-04 CLJ-872 Add support for prop lookup, refs CLJS-89
191 [(keyword fld)
192 `(reify clojure.lang.ILookupThunk
193 (get [~'thunk ~'gtarget]
194 (if (identical? (class ~'gtarget) ~'gclass)
195 (. ~hinted-target ~(symbol (str "-" fld)))
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
196 ~'thunk)))])
197 base-fields))
198 nil))))])
eea980a7 » richhickey
2009-10-30 IPersistentMap opt-in, dissoc support, doc tweaks
199 (imap [[i m]]
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
200 [(conj i 'clojure.lang.IPersistentMap)
201 (conj m
c2b229e6 » khinsen
2010-05-28 Remove potential conflicts between field names and method argument na…
202 `(count [this#] (+ ~(count base-fields) (count ~'__extmap)))
203 `(empty [this#] (throw (UnsupportedOperationException. (str "Can't create empty: " ~(str classname)))))
204 `(cons [this# e#] ((var imap-cons) this# e#))
ac484ba4 » richhickey
2010-08-04 fix record equality with other maps, = includes type, .equals doesn't…
205 `(equiv [this# ~gs]
206 (boolean
207 (or (identical? this# ~gs)
208 (when (identical? (class this#) (class ~gs))
209 (let [~gs ~(with-meta gs {:tag tagname})]
595d0f7a » Michael Fogus and Alan Dipert
2011-11-04 CLJ-872 Add support for prop lookup, refs CLJS-89
210 (and ~@(map (fn [fld] `(= ~fld (. ~gs ~(symbol (str "-" fld))))) base-fields)
ac484ba4 » richhickey
2010-08-04 fix record equality with other maps, = includes type, .equals doesn't…
211 (= ~'__extmap (. ~gs ~'__extmap))))))))
c2b229e6 » khinsen
2010-05-28 Remove potential conflicts between field names and method argument na…
212 `(containsKey [this# k#] (not (identical? this# (.valAt this# k# this#))))
213 `(entryAt [this# k#] (let [v# (.valAt this# k# this#)]
214 (when-not (identical? this# v#)
215 (clojure.lang.MapEntry. k# v#))))
ec2037e5 » stuarthalloway
2010-07-14 fix degenerate defrecords, #402
216 `(seq [this#] (seq (concat [~@(map #(list `new `clojure.lang.MapEntry (keyword %) %) base-fields)]
217 ~'__extmap)))
4e64fa21 » richhickey
2012-04-09 deftype failed to implement Iterable
218 `(iterator [this#] (clojure.lang.SeqIterator. (.seq this#)))
c2b229e6 » khinsen
2010-05-28 Remove potential conflicts between field names and method argument na…
219 `(assoc [this# k# ~gs]
220 (condp identical? k#
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
221 ~@(mapcat (fn [fld]
c2b229e6 » khinsen
2010-05-28 Remove potential conflicts between field names and method argument na…
222 [(keyword fld) (list* `new tagname (replace {fld gs} fields))])
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
223 base-fields)
c2b229e6 » khinsen
2010-05-28 Remove potential conflicts between field names and method argument na…
224 (new ~tagname ~@(remove #{'__extmap} fields) (assoc ~'__extmap k# ~gs))))
225 `(without [this# k#] (if (contains? #{~@(map keyword base-fields)} k#)
226 (dissoc (with-meta (into {} this#) ~'__meta) k#)
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
227 (new ~tagname ~@(remove #{'__extmap} fields)
c2b229e6 » khinsen
2010-05-28 Remove potential conflicts between field names and method argument na…
228 (not-empty (dissoc ~'__extmap k#))))))])
c487e48a » stuarthalloway
2010-04-23 java.util.Map for defrecord, #313
229 (ijavamap [[i m]]
f0cfe0a7 » richhickey
2010-04-27 made defrecords Serializable
230 [(conj i 'java.util.Map 'java.io.Serializable)
c487e48a » stuarthalloway
2010-04-23 java.util.Map for defrecord, #313
231 (conj m
c2b229e6 » khinsen
2010-05-28 Remove potential conflicts between field names and method argument na…
232 `(size [this#] (.count this#))
233 `(isEmpty [this#] (= 0 (.count this#)))
ec2037e5 » stuarthalloway
2010-07-14 fix degenerate defrecords, #402
234 `(containsValue [this# v#] (boolean (some #{v#} (vals this#))))
c2b229e6 » khinsen
2010-05-28 Remove potential conflicts between field names and method argument na…
235 `(get [this# k#] (.valAt this# k#))
236 `(put [this# k# v#] (throw (UnsupportedOperationException.)))
237 `(remove [this# k#] (throw (UnsupportedOperationException.)))
238 `(putAll [this# m#] (throw (UnsupportedOperationException.)))
239 `(clear [this#] (throw (UnsupportedOperationException.)))
240 `(keySet [this#] (set (keys this#)))
241 `(values [this#] (vals this#))
242 `(entrySet [this#] (set this#)))])
c487e48a » stuarthalloway
2010-04-23 java.util.Map for defrecord, #313
243 ]
ac1e8ad9 » fogus
2011-05-10 Changes to support defrecord and deftype literals. See CLJ-374
244 (let [[i m] (-> [interfaces methods] irecord eqhash iobj ilookup imap ijavamap)]
292836f8 » richhickey
2009-11-12 got rid of defclass. deftype now can refer to self-type, will emit sa…
245 `(deftype* ~tagname ~classname ~(conj hinted-fields '__meta '__extmap)
5f090a09 » richhickey
2009-10-28 first cut at defclass/deftype
246 :implements ~(vec i)
c2b229e6 » khinsen
2010-05-28 Remove potential conflicts between field names and method argument na…
247 ~@m))))))
5f090a09 » richhickey
2009-10-28 first cut at defclass/deftype
248
21175bc9 » fogus
2011-05-24 Changes to shore up the shortcomings and fix bugs found in defrecord …
249 (defn- build-positional-factory
250 "Used to build a positional factory for a given type/record. Because of the
251 limitation of 20 arguments to Clojure functions, this factory needs to be
252 constructed to deal with more arguments. It does this by building a straight
253 forward type/record ctor call in the <=20 case, and a call to the same
254 ctor pulling the extra args out of the & overage parameter. Finally, the
255 arity is constrained to the number of expected fields and an ArityException
256 will be thrown at runtime if the actual arg count does not match."
257 [nom classname fields]
258 (let [fn-name (symbol (str '-> nom))
259 [field-args over] (split-at 20 fields)
260 field-count (count fields)
261 arg-count (count field-args)
9e28ceda » grammati
2012-02-17 Docstrings for generated factory functions.
262 over-count (count over)
263 docstring (str "Positional factory function for class " classname ".")]
21175bc9 » fogus
2011-05-24 Changes to shore up the shortcomings and fix bugs found in defrecord …
264 `(defn ~fn-name
9e28ceda » grammati
2012-02-17 Docstrings for generated factory functions.
265 ~docstring
21175bc9 » fogus
2011-05-24 Changes to shore up the shortcomings and fix bugs found in defrecord …
266 [~@field-args ~@(if (seq over) '[& overage] [])]
267 ~(if (seq over)
268 `(if (= (count ~'overage) ~over-count)
269 (new ~classname
270 ~@field-args
271 ~@(for [i (range 0 (count over))]
272 (list `nth 'overage i)))
273 (throw (clojure.lang.ArityException. (+ ~arg-count (count ~'overage)) (name '~fn-name))))
274 `(new ~classname ~@field-args)))))
275
31557461 » fogus
2011-09-12 Fixes CLJ-837 by allowing any field prefixed with double-underscores …
276 (defn- validate-fields
277 ""
278 [fields]
d50cebbc » tsdh
2011-12-23 Don't use descructuring in defrecord/deftype arglists to get a slight…
279 (when-not (vector? fields)
280 (throw (AssertionError. "No fields vector given.")))
31557461 » fogus
2011-09-12 Fixes CLJ-837 by allowing any field prefixed with double-underscores …
281 (let [specials #{'__meta '__extmap}]
282 (when (some specials fields)
283 (throw (AssertionError. (str "The names in " specials " cannot be used as field names for types or records."))))))
284
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
285 (defmacro defrecord
93d13d0c » puredanger
2013-11-07 Remove Alpha designation from many features.
286 "(defrecord name [fields*] options* specs*)
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
287
ba6cc3bd » richhickey
2010-04-02 reify/deftype methods now take target ('this') object as explicit fir…
288 Currently there are no options.
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
289
290 Each spec consists of a protocol or interface name followed by zero
291 or more method bodies:
292
293 protocol-or-interface-or-Object
294 (methodName [args*] body)*
a84a4e1f » richhickey
2009-11-30 deftype and reify support direct implementation of protocols
295
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
296 Dynamically generates compiled bytecode for class with the given
297 name, in a package with the same name as the current namespace, the
298 given fields, and, optionally, methods for protocols and/or
299 interfaces.
5f090a09 » richhickey
2009-10-28 first cut at defclass/deftype
300
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
301 The class will have the (immutable) fields named by
23f612ed » richhickey
2010-02-16 added :volatile-mutable and :unsynchronized-mutable options to deftyp…
302 fields, which can have type hints. Protocols/interfaces and methods
303 are optional. The only methods that can be supplied are those
304 declared in the protocols/interfaces. Note that method bodies are
305 not closures, the local environment includes only the named fields,
5fcdc6eb » cldwalker
2013-07-01 fix typos in docstrings and docs
306 and those fields can be accessed directly.
9c3e97a8 » richhickey
2009-10-30 methodnames now take form (.methodname [args] body) in reify/deftype/…
307
308 Method definitions take the form:
309
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
310 (methodname [args*] body)
9c3e97a8 » richhickey
2009-10-30 methodnames now take form (.methodname [args] body) in reify/deftype/…
311
312 The argument and return types can be hinted on the arg and
313 methodname symbols. If not supplied, they will be inferred, so type
314 hints should be reserved for disambiguation.
eea980a7 » richhickey
2009-10-30 IPersistentMap opt-in, dissoc support, doc tweaks
315
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
316 Methods should be supplied for all methods of the desired
317 protocol(s) and interface(s). You can also define overrides for
ba6cc3bd » richhickey
2010-04-02 reify/deftype methods now take target ('this') object as explicit fir…
318 methods of Object. Note that a parameter must be supplied to
319 correspond to the target object ('this' in Java parlance). Thus
320 methods for interfaces will take one more argument than do the
321 interface declarations. Note also that recur calls to the method
322 head should *not* pass the target object, it will be supplied
323 automatically and can not be substituted.
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
324
292836f8 » richhickey
2009-11-12 got rid of defclass. deftype now can refer to self-type, will emit sa…
325 In the method bodies, the (unqualified) name can be used to name the
326 class (for calls to new, instance? etc).
327
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
328 The class will have implementations of several (clojure.lang)
329 interfaces generated automatically: IObj (metadata support) and
330 IPersistentMap, and all of their superinterfaces.
eea980a7 » richhickey
2009-10-30 IPersistentMap opt-in, dissoc support, doc tweaks
331
6d84867f » stuarthalloway
2011-09-02 CLJ-736 docfix
332 In addition, defrecord will define type-and-value-based =,
333 and will defined Java .hashCode and .equals consistent with the
334 contract for java.util.Map.
eea980a7 » richhickey
2009-10-30 IPersistentMap opt-in, dissoc support, doc tweaks
335
292836f8 » richhickey
2009-11-12 got rid of defclass. deftype now can refer to self-type, will emit sa…
336 When AOT compiling, generates compiled bytecode for a class with the
337 given name (a symbol), prepends the current ns as the package, and
a84a4e1f » richhickey
2009-11-30 deftype and reify support direct implementation of protocols
338 writes the .class file to the *compile-path* directory.
292836f8 » richhickey
2009-11-12 got rid of defclass. deftype now can refer to self-type, will emit sa…
339
340 Two constructors will be defined, one taking the designated fields
341 followed by a metadata map (nil for none) and an extension field
342 map (nil for none), and one taking only the fields (using nil for
31557461 » fogus
2011-09-12 Fixes CLJ-837 by allowing any field prefixed with double-underscores …
343 meta and extension fields). Note that the field names __meta
344 and __extmap are currently reserved and should not be used when
9e28ceda » grammati
2012-02-17 Docstrings for generated factory functions.
345 defining your own records.
346
347 Given (defrecord TypeName ...), two factory functions will be
348 defined: ->TypeName, taking positional parameters for the fields,
349 and map->TypeName, taking a map of keywords to field values."
d50cebbc » tsdh
2011-12-23 Don't use descructuring in defrecord/deftype arglists to get a slight…
350 {:added "1.2"
351 :arglists '([name [& fields] & opts+specs])}
5f090a09 » richhickey
2009-10-28 first cut at defclass/deftype
352
d50cebbc » tsdh
2011-12-23 Don't use descructuring in defrecord/deftype arglists to get a slight…
353 [name fields & opts+specs]
31557461 » fogus
2011-09-12 Fixes CLJ-837 by allowing any field prefixed with double-underscores …
354 (validate-fields fields)
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
355 (let [gname name
f612ecff » richhickey
2010-02-10 inlined bit shifts, added definterface (undocumented for now)
356 [interfaces methods opts] (parse-opts+specs opts+specs)
ac1e8ad9 » fogus
2011-05-10 Changes to support defrecord and deftype literals. See CLJ-374
357 ns-part (namespace-munge *ns*)
358 classname (symbol (str ns-part "." gname))
a3d42748 » richhickey
2009-10-29 don't propagate field hints into method bodies
359 hinted-fields fields
292836f8 » richhickey
2009-11-12 got rid of defclass. deftype now can refer to self-type, will emit sa…
360 fields (vec (map #(with-meta % nil) fields))]
2ac93197 » richhickey
2010-06-06 prevent dynamic classes from being flushed before use
361 `(let []
8a0482d3 » kurtharriger
2011-11-11 declare record factory functions for use within defrecord implementation
362 (declare ~(symbol (str '-> gname)))
363 (declare ~(symbol (str 'map-> gname)))
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
364 ~(emit-defrecord name gname (vec hinted-fields) (vec interfaces) methods)
365 (import ~classname)
21175bc9 » fogus
2011-05-24 Changes to shore up the shortcomings and fix bugs found in defrecord …
366 ~(build-positional-factory gname classname fields)
367 (defn ~(symbol (str 'map-> gname))
9e28ceda » grammati
2012-02-17 Docstrings for generated factory functions.
368 ~(str "Factory function for class " classname ", taking a map of keywords to field values.")
ac1e8ad9 » fogus
2011-05-10 Changes to support defrecord and deftype literals. See CLJ-374
369 ([m#] (~(symbol (str classname "/create")) m#)))
370 ~classname)))
766b248f » richhickey
2009-11-11 first cut at protocols
371
f7215fdb » devn
2013-11-22 Add record? via IRecord
372 (defn record?
373 "Returns true if x is a record"
374 {:added "1.6"
375 :static true}
376 [x]
377 (instance? clojure.lang.IRecord x))
378
379 (defn- emit-deftype*
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
380 "Do not use this directly - use deftype"
381 [tagname name fields interfaces methods]
21175bc9 » fogus
2011-05-24 Changes to shore up the shortcomings and fix bugs found in defrecord …
382 (let [classname (with-meta (symbol (str (namespace-munge *ns*) "." name)) (meta name))
383 interfaces (conj interfaces 'clojure.lang.IType)]
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
384 `(deftype* ~tagname ~classname ~fields
385 :implements ~interfaces
386 ~@methods)))
387
388 (defmacro deftype
93d13d0c » puredanger
2013-11-07 Remove Alpha designation from many features.
389 "(deftype name [fields*] options* specs*)
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
390
391 Currently there are no options.
392
393 Each spec consists of a protocol or interface name followed by zero
394 or more method bodies:
395
396 protocol-or-interface-or-Object
397 (methodName [args*] body)*
398
399 Dynamically generates compiled bytecode for class with the given
400 name, in a package with the same name as the current namespace, the
401 given fields, and, optionally, methods for protocols and/or
402 interfaces.
403
404 The class will have the (by default, immutable) fields named by
405 fields, which can have type hints. Protocols/interfaces and methods
406 are optional. The only methods that can be supplied are those
407 declared in the protocols/interfaces. Note that method bodies are
408 not closures, the local environment includes only the named fields,
409 and those fields can be accessed directy. Fields can be qualified
410 with the metadata :volatile-mutable true or :unsynchronized-mutable
411 true, at which point (set! afield aval) will be supported in method
412 bodies. Note well that mutable fields are extremely difficult to use
413 correctly, and are present only to facilitate the building of higher
414 level constructs, such as Clojure's reference types, in Clojure
415 itself. They are for experts only - if the semantics and
416 implications of :volatile-mutable or :unsynchronized-mutable are not
417 immediately apparent to you, you should not be using them.
418
419 Method definitions take the form:
420
421 (methodname [args*] body)
422
423 The argument and return types can be hinted on the arg and
424 methodname symbols. If not supplied, they will be inferred, so type
425 hints should be reserved for disambiguation.
426
427 Methods should be supplied for all methods of the desired
428 protocol(s) and interface(s). You can also define overrides for
429 methods of Object. Note that a parameter must be supplied to
430 correspond to the target object ('this' in Java parlance). Thus
431 methods for interfaces will take one more argument than do the
432 interface declarations. Note also that recur calls to the method
433 head should *not* pass the target object, it will be supplied
434 automatically and can not be substituted.
435
436 In the method bodies, the (unqualified) name can be used to name the
437 class (for calls to new, instance? etc).
438
439 When AOT compiling, generates compiled bytecode for a class with the
440 given name (a symbol), prepends the current ns as the package, and
441 writes the .class file to the *compile-path* directory.
442
31557461 » fogus
2011-09-12 Fixes CLJ-837 by allowing any field prefixed with double-underscores …
443 One constructor will be defined, taking the designated fields. Note
444 that the field names __meta and __extmap are currently reserved and
9e28ceda » grammati
2012-02-17 Docstrings for generated factory functions.
445 should not be used when defining your own types.
446
447 Given (deftype TypeName ...), a factory function called ->TypeName
448 will be defined, taking positional parameters for the fields"
d50cebbc » tsdh
2011-12-23 Don't use descructuring in defrecord/deftype arglists to get a slight…
449 {:added "1.2"
450 :arglists '([name [& fields] & opts+specs])}
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
451
d50cebbc » tsdh
2011-12-23 Don't use descructuring in defrecord/deftype arglists to get a slight…
452 [name fields & opts+specs]
31557461 » fogus
2011-09-12 Fixes CLJ-837 by allowing any field prefixed with double-underscores …
453 (validate-fields fields)
1eb87864 » richhickey
2010-04-15 doc fix, remove reference to factory fns
454 (let [gname name
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
455 [interfaces methods opts] (parse-opts+specs opts+specs)
ac1e8ad9 » fogus
2011-05-10 Changes to support defrecord and deftype literals. See CLJ-374
456 ns-part (namespace-munge *ns*)
457 classname (symbol (str ns-part "." gname))
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
458 hinted-fields fields
21175bc9 » fogus
2011-05-24 Changes to shore up the shortcomings and fix bugs found in defrecord …
459 fields (vec (map #(with-meta % nil) fields))
460 [field-args over] (split-at 20 fields)]
2ac93197 » richhickey
2010-06-06 prevent dynamic classes from being flushed before use
461 `(let []
12b5c599 » richhickey
2010-04-14 first cut of deftype/defrecord split
462 ~(emit-deftype* name gname (vec hinted-fields) (vec interfaces) methods)
ac1e8ad9 » fogus
2011-05-10 Changes to support defrecord and deftype literals. See CLJ-374
463 (import ~classname)
21175bc9 » fogus
2011-05-24 Changes to shore up the shortcomings and fix bugs found in defrecord …
464 ~(build-positional-factory gname classname fields)
ac1e8ad9 » fogus
2011-05-10 Changes to support defrecord and deftype literals. See CLJ-374
465 ~classname)))
466
766b248f » richhickey
2009-11-11 first cut at protocols
467 ;;;;;;;;;;;;;;;;;;;;;;; protocols ;;;;;;;;;;;;;;;;;;;;;;;;
468
78793836 » richhickey
2010-04-26 replace #^s with ^s
469 (defn- expand-method-impl-cache [^clojure.lang.MethodImplCache cache c f]
8b94a540 » Alexander Taggart
2011-05-21 Fix CLJ-801: protocol's method cache falls back to using a map when s…
470 (if (.map cache)
471 (let [cs (assoc (.map cache) c (clojure.lang.MethodImplCache$Entry. c f))]
472 (clojure.lang.MethodImplCache. (.protocol cache) (.methodk cache) cs))
473 (let [cs (into1 {} (remove (fn [[c e]] (nil? e)) (map vec (partition 2 (.table cache)))))
474 cs (assoc cs c (clojure.lang.MethodImplCache$Entry. c f))]
475 (if-let [[shift mask] (maybe-min-hash (map hash (keys cs)))]
476 (let [table (make-array Object (* 2 (inc mask)))
477 table (reduce1 (fn [^objects t [c e]]
478 (let [i (* 2 (int (shift-mask shift mask (hash c))))]
479 (aset t i c)
480 (aset t (inc i) e)
481 t))
482 table cs)]
483 (clojure.lang.MethodImplCache. (.protocol cache) (.methodk cache) shift mask table))
484 (clojure.lang.MethodImplCache. (.protocol cache) (.methodk cache) cs)))))
766b248f » richhickey
2009-11-11 first cut at protocols
485
78793836 » richhickey
2010-04-26 replace #^s with ^s
486 (defn- super-chain [^Class c]
bebb1ff5 » richhickey
2009-11-12 use hierarchy to determine impl given multiple extends in superclasse…
487 (when c
488 (cons c (super-chain (.getSuperclass c)))))
489
eba23dbd » richhickey
2010-04-17 prefer more derived interface in protocol, fixes #302
490 (defn- pref
491 ([] nil)
492 ([a] a)
78793836 » richhickey
2010-04-26 replace #^s with ^s
493 ([^Class a ^Class b]
eba23dbd » richhickey
2010-04-17 prefer more derived interface in protocol, fixes #302
494 (if (.isAssignableFrom a b) b a)))
495
766b248f » richhickey
2009-11-11 first cut at protocols
496 (defn find-protocol-impl [protocol x]
ba9b7924 » richhickey
2010-04-15 remove IDynamicType and type tags
497 (if (instance? (:on-interface protocol) x)
d923bb24 » richhickey
2009-11-21 direct calls through to on interface methods
498 x
ba9b7924 » richhickey
2010-04-15 remove IDynamicType and type tags
499 (let [c (class x)
500 impl #(get (:impls protocol) %)]
501 (or (impl c)
502 (and c (or (first (remove nil? (map impl (butlast (super-chain c)))))
3f74c9ff » richhickey
2010-06-11 re-enable protocol-based reduce
503 (when-let [t (reduce1 pref (filter impl (disj (supers c) Object)))]
eba23dbd » richhickey
2010-04-17 prefer more derived interface in protocol, fixes #302
504 (impl t))
d923bb24 » richhickey
2009-11-21 direct calls through to on interface methods
505 (impl Object)))))))
766b248f » richhickey
2009-11-11 first cut at protocols
506
507 (defn find-protocol-method [protocol methodk x]
508 (get (find-protocol-impl protocol x) methodk))
509
33a3759f » stuarthalloway
2010-05-04 more protocol tests, fixed NPE in extend, #239
510 (defn- protocol?
511 [maybe-p]
512 (boolean (:on-interface maybe-p)))
513
f47895ad » richhickey
2010-04-16 check that type does not already implement protocol interface when ex…
514 (defn- implements? [protocol atype]
78793836 » richhickey
2010-04-26 replace #^s with ^s
515 (and atype (.isAssignableFrom ^Class (:on-interface protocol) atype)))
f47895ad » richhickey
2010-04-16 check that type does not already implement protocol interface when ex…
516
766b248f » richhickey
2009-11-11 first cut at protocols
517 (defn extends?
ba9b7924 » richhickey
2010-04-15 remove IDynamicType and type tags
518 "Returns true if atype extends protocol"
c1c39162 » stuarthalloway
2010-04-29 metadata for :added
519 {:added "1.2"}
766b248f » richhickey
2009-11-11 first cut at protocols
520 [protocol atype]
f47895ad » richhickey
2010-04-16 check that type does not already implement protocol interface when ex…
521 (boolean (or (implements? protocol atype)
ba9b7924 » richhickey
2010-04-15 remove IDynamicType and type tags
522 (get (:impls protocol) atype))))
766b248f » richhickey
2009-11-11 first cut at protocols
523
524 (defn extenders
525 "Returns a collection of the types explicitly extending protocol"
c1c39162 » stuarthalloway
2010-04-29 metadata for :added
526 {:added "1.2"}
766b248f » richhickey
2009-11-11 first cut at protocols
527 [protocol]
528 (keys (:impls protocol)))
529
530 (defn satisfies?
531 "Returns true if x satisfies the protocol"
c1c39162 » stuarthalloway
2010-04-29 metadata for :added
532 {:added "1.2"}
766b248f » richhickey
2009-11-11 first cut at protocols
533 [protocol x]
ba9b7924 » richhickey
2010-04-15 remove IDynamicType and type tags
534 (boolean (find-protocol-impl protocol x)))
766b248f » richhickey
2009-11-11 first cut at protocols
535
78793836 » richhickey
2010-04-26 replace #^s with ^s
536 (defn -cache-protocol-fn [^clojure.lang.AFunction pf x ^Class c ^clojure.lang.IFn interf]
8c16415f » richhickey
2009-11-14 put method impl cache on fns themselves, get rid of box
537 (let [cache (.__methodImplCache pf)
e660e467 » richhickey
2010-04-19 new perf for protocols
538 f (if (.isInstance c x)
539 interf
540 (find-protocol-method (.protocol cache) (.methodk cache) x))]
766b248f » richhickey
2009-11-11 first cut at protocols
541 (when-not f
542 (throw (IllegalArgumentException. (str "No implementation of method: " (.methodk cache)
543 " of protocol: " (:var (.protocol cache))
63476312 » richhickey
2009-11-12 make protocol cache/satisfies? nil-tolerant, ditto supers/bases
544 " found for class: " (if (nil? x) "nil" (.getName (class x)))))))
8c16415f » richhickey
2009-11-14 put method impl cache on fns themselves, get rid of box
545 (set! (.__methodImplCache pf) (expand-method-impl-cache cache (class x) f))
766b248f » richhickey
2009-11-11 first cut at protocols
546 f))
547
d923bb24 » richhickey
2009-11-21 direct calls through to on interface methods
548 (defn- emit-method-builder [on-interface method on-method arglists]
766b248f » richhickey
2009-11-11 first cut at protocols
549 (let [methodk (keyword method)
e660e467 » richhickey
2010-04-19 new perf for protocols
550 gthis (with-meta (gensym) {:tag 'clojure.lang.AFunction})
551 ginterf (gensym)]
8c16415f » richhickey
2009-11-14 put method impl cache on fns themselves, get rid of box
552 `(fn [cache#]
e660e467 » richhickey
2010-04-19 new perf for protocols
553 (let [~ginterf
554 (fn
555 ~@(map
556 (fn [args]
557 (let [gargs (map #(gensym (str "gf__" % "__")) args)
558 target (first gargs)]
559 `([~@gargs]
98437ff5 » amalloy
2013-04-18 Fix CLJ-1202.
560 (. ~(with-meta target {:tag on-interface}) (~(or on-method method) ~@(rest gargs))))))
e660e467 » richhickey
2010-04-19 new perf for protocols
561 arglists))
78793836 » richhickey
2010-04-26 replace #^s with ^s
562 ^clojure.lang.AFunction f#
8c16415f » richhickey
2009-11-14 put method impl cache on fns themselves, get rid of box
563 (fn ~gthis
564 ~@(map
565 (fn [args]
19dd3c59 » richhickey
2010-04-18 Remove perf hacks from MethodImplCache, restore new reduce impl
566 (let [gargs (map #(gensym (str "gf__" % "__")) args)
8c16415f » richhickey
2009-11-14 put method impl cache on fns themselves, get rid of box
567 target (first gargs)]
568 `([~@gargs]
e660e467 » richhickey
2010-04-19 new perf for protocols
569 (let [cache# (.__methodImplCache ~gthis)
570 f# (.fnFor cache# (clojure.lang.Util/classOf ~target))]
571 (if f#
572 (f# ~@gargs)
573 ((-cache-protocol-fn ~gthis ~target ~on-interface ~ginterf) ~@gargs))))))
8c16415f » richhickey
2009-11-14 put method impl cache on fns themselves, get rid of box
574 arglists))]
575 (set! (.__methodImplCache f#) cache#)
576 f#))))
766b248f » richhickey
2009-11-11 first cut at protocols
577
578 (defn -reset-methods [protocol]
78793836 » richhickey
2010-04-26 replace #^s with ^s
579 (doseq [[^clojure.lang.Var v build] (:method-builders protocol)]
8c16415f » richhickey
2009-11-14 put method impl cache on fns themselves, get rid of box
580 (let [cache (clojure.lang.MethodImplCache. protocol (keyword (.sym v)))]
581 (.bindRoot v (build cache)))))
766b248f » richhickey
2009-11-11 first cut at protocols
582
1efc4954 » Chouser
2009-11-12 defprotocol now warns when it overwrites an exising method var
583 (defn- assert-same-protocol [protocol-var method-syms]
584 (doseq [m method-syms]
585 (let [v (resolve m)
586 p (:protocol (meta v))]
8eebaa15 » richhickey
2010-04-15 don't warn on unbound protocol vars
587 (when (and v (bound? v) (not= protocol-var p))
1efc4954 » Chouser
2009-11-12 defprotocol now warns when it overwrites an exising method var
588 (binding [*out* *err*]
589 (println "Warning: protocol" protocol-var "is overwriting"
590 (if p
591 (str "method " (.sym v) " of protocol " (.sym p))
592 (str "function " (.sym v)))))))))
593
766b248f » richhickey
2009-11-11 first cut at protocols
594 (defn- emit-protocol [name opts+sigs]
c6e7e576 » cemerick
2010-11-19 properly munge namespaces -> java package names for protocols and def…
595 (let [iname (symbol (str (munge (namespace-munge *ns*)) "." (munge name)))
77173bbf » richhickey
2009-11-30 protocols gen interface of same name, e.g. my.ns/Protocol gens my.ns.…
596 [opts sigs]
dd152aed » richhickey
2009-11-30 add :on-interface for code requiring class, since :on now symbol
597 (loop [opts {:on (list 'quote iname) :on-interface iname} sigs opts+sigs]
766b248f » richhickey
2009-11-11 first cut at protocols
598 (condp #(%1 %2) (first sigs)
599 string? (recur (assoc opts :doc (first sigs)) (next sigs))
600 keyword? (recur (assoc opts (first sigs) (second sigs)) (nnext sigs))
601 [opts sigs]))
2bc8b1f5 » Bronsa
2012-04-05 Added support for marker protocols
602 sigs (when sigs
603 (reduce1 (fn [m s]
604 (let [name-meta (meta (first s))
605 mname (with-meta (first s) nil)
606 [arglists doc]
607 (loop [as [] rs (rest s)]
608 (if (vector? (first rs))
609 (recur (conj as (first rs)) (next rs))
610 [(seq as) (first rs)]))]
611 (when (some #{0} (map count arglists))
f9792907 » puredanger
2013-10-18 CLJ-1056: improves defprotocol error messages for no args and redefin…
612 (throw (IllegalArgumentException. (str "Definition of function " mname " in protocol " name " must take at least one arg."))))
613 (when (m (keyword mname))
614 (throw (IllegalArgumentException. (str "Function " mname " in protocol " name " was redefined. Specify all arities in single definition."))))
2bc8b1f5 » Bronsa
2012-04-05 Added support for marker protocols
615 (assoc m (keyword mname)
616 (merge name-meta
617 {:name (vary-meta mname assoc :doc doc :arglists arglists)
618 :arglists arglists
619 :doc doc}))))
620 {} sigs))
77173bbf » richhickey
2009-11-30 protocols gen interface of same name, e.g. my.ns/Protocol gens my.ns.…
621 meths (mapcat (fn [sig]
622 (let [m (munge (:name sig))]
623 (map #(vector m (vec (repeat (dec (count %))'Object)) 'Object)
624 (:arglists sig))))
625 (vals sigs))]
766b248f » richhickey
2009-11-11 first cut at protocols
626 `(do
627 (defonce ~name {})
77173bbf » richhickey
2009-11-30 protocols gen interface of same name, e.g. my.ns/Protocol gens my.ns.…
628 (gen-interface :name ~iname :methods ~meths)
1efc4954 » Chouser
2009-11-12 defprotocol now warns when it overwrites an exising method var
629 (alter-meta! (var ~name) assoc :doc ~(:doc opts))
2bc8b1f5 » Bronsa
2012-04-05 Added support for marker protocols
630 ~(when sigs
631 `(#'assert-same-protocol (var ~name) '~(map :name (vals sigs))))
766b248f » richhickey
2009-11-11 first cut at protocols
632 (alter-var-root (var ~name) merge
633 (assoc ~opts
634 :sigs '~sigs
635 :var (var ~name)
d923bb24 » richhickey
2009-11-21 direct calls through to on interface methods
636 :method-map
637 ~(and (:on opts)
638 (apply hash-map
639 (mapcat
640 (fn [s]
641 [(keyword (:name s)) (keyword (or (:on s) (:name s)))])
642 (vals sigs))))
766b248f » richhickey
2009-11-11 first cut at protocols
643 :method-builders
644 ~(apply hash-map
645 (mapcat
8c9b0574 » stuarthalloway
2010-05-22 propagate useful metadata to protocol fns #349
646 (fn [s]
647 [`(intern *ns* (with-meta '~(:name s) (merge '~s {:protocol (var ~name)})))
dd152aed » richhickey
2009-11-30 add :on-interface for code requiring class, since :on now symbol
648 (emit-method-builder (:on-interface opts) (:name s) (:on s) (:arglists s))])
766b248f » richhickey
2009-11-11 first cut at protocols
649 (vals sigs)))))
650 (-reset-methods ~name)
651 '~name)))
652
653 (defmacro defprotocol
654 "A protocol is a named set of named methods and their signatures:
655 (defprotocol AProtocolName
656
2c25d62e » richhickey
2009-12-02 doc fix
657 ;optional doc string
658 \"A doc string for AProtocol abstraction\"
766b248f » richhickey
2009-11-11 first cut at protocols
659
660 ;method signatures
befba000 » Fogus
2010-05-05 Fixes missing this arg on the reify and defprotocol docstrings #340
661 (bar [this a b] \"bar docs\")
662 (baz [this a] [this a b] [this a b c] \"baz docs\"))
766b248f » richhickey
2009-11-11 first cut at protocols
663
664 No implementations are provided. Docs can be specified for the
665 protocol overall and for each method. The above yields a set of
666 polymorphic functions and a protocol object. All are
667 namespace-qualified by the ns enclosing the definition The resulting
befba000 » Fogus
2010-05-05 Fixes missing this arg on the reify and defprotocol docstrings #340
668 functions dispatch on the type of their first argument, which is
669 required and corresponds to the implicit target object ('this' in
670 Java parlance). defprotocol is dynamic, has no special compile-time
671 effect, and defines no new types or classes. Implementations of
672 the protocol methods can be provided using extend.
a84a4e1f » richhickey
2009-11-30 deftype and reify support direct implementation of protocols
673
674 defprotocol will automatically generate a corresponding interface,
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
675 with the same name as the protocol, i.e. given a protocol:
676 my.ns/Protocol, an interface: my.ns.Protocol. The interface will
a84a4e1f » richhickey
2009-11-30 deftype and reify support direct implementation of protocols
677 have methods corresponding to the protocol functions, and the
678 protocol will automatically work with instances of the interface.
679
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
680 Note that you should not use this interface with deftype or
a84a4e1f » richhickey
2009-11-30 deftype and reify support direct implementation of protocols
681 reify, as they support the protocol directly:
682
683 (defprotocol P
befba000 » Fogus
2010-05-05 Fixes missing this arg on the reify and defprotocol docstrings #340
684 (foo [this])
685 (bar-me [this] [this y]))
a84a4e1f » richhickey
2009-11-30 deftype and reify support direct implementation of protocols
686
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
687 (deftype Foo [a b c]
688 P
befba000 » Fogus
2010-05-05 Fixes missing this arg on the reify and defprotocol docstrings #340
689 (foo [this] a)
690 (bar-me [this] b)
691 (bar-me [this y] (+ c y)))
a84a4e1f » richhickey
2009-11-30 deftype and reify support direct implementation of protocols
692
befba000 » Fogus
2010-05-05 Fixes missing this arg on the reify and defprotocol docstrings #340
693 (bar-me (Foo. 1 2 3) 42)
694 => 45
a84a4e1f » richhickey
2009-11-30 deftype and reify support direct implementation of protocols
695
696 (foo
697 (let [x 42]
4d3c5e9f » richhickey
2009-12-04 new formats for defprotocol, reify, deftype
698 (reify P
befba000 » Fogus
2010-05-05 Fixes missing this arg on the reify and defprotocol docstrings #340
699 (foo [this] 17)
700 (bar-me [this] x)
701 (bar-me [this y] x))))
702 => 17"
c1c39162 » stuarthalloway
2010-04-29 metadata for :added
703 {:added "1.2"}
766b248f » richhickey
2009-11-11 first cut at protocols
704 [name & opts+sigs]
705 (emit-protocol name opts+sigs))
706
707 (defn extend
708 "Implementations of protocol methods can be provided using the extend construct:
709
ba9b7924 » richhickey
2010-04-15 remove IDynamicType and type tags
710 (extend AType
766b248f » richhickey
2009-11-11 first cut at protocols
711 AProtocol
712 {:foo an-existing-fn
713 :bar (fn [a b] ...)
714 :baz (fn ([a]...) ([a b] ...)...)}
715 BProtocol
716 {...}
717 ...)
718
719 extend takes a type/class (or interface, see below), and one or more
720 protocol + method map pairs. It will extend the polymorphism of the
721 protocol's methods to call the supplied methods when an AType is
ba9b7924 » richhickey
2010-04-15 remove IDynamicType and type tags
722 provided as the first argument.
766b248f » richhickey
2009-11-11 first cut at protocols
723
724 Method maps are maps of the keyword-ized method names to ordinary
725 fns. This facilitates easy reuse of existing fns and fn maps, for
726 code reuse/mixins without derivation or composition. You can extend
727 an interface to a protocol. This is primarily to facilitate interop
728 with the host (e.g. Java) but opens the door to incidental multiple
729 inheritance of implementation since a class can inherit from more
730 than one interface, both of which extend the protocol. It is TBD how
731 to specify which impl to use. You can extend a protocol on nil.
732
18f1c963 » richhickey
2009-11-16 added extend-type and extend-class
733 If you are supplying the definitions explicitly (i.e. not reusing
734 exsting functions or mixin maps), you may find it more convenient to
ba9b7924 » richhickey
2010-04-15 remove IDynamicType and type tags
735 use the extend-type or extend-protocol macros.
18f1c963 » richhickey
2009-11-16 added extend-type and extend-class
736
766b248f » richhickey
2009-11-11 first cut at protocols
737 Note that multiple independent extend clauses can exist for the same
738 type, not all protocols need be defined in a single extend call.
739
740 See also:
741 extends?, satisfies?, extenders"
c1c39162 » stuarthalloway
2010-04-29 metadata for :added
742 {:added "1.2"}
766b248f » richhickey
2009-11-11 first cut at protocols
743 [atype & proto+mmaps]
744 (doseq [[proto mmap] (partition 2 proto+mmaps)]
33a3759f » stuarthalloway
2010-05-04 more protocol tests, fixed NPE in extend, #239
745 (when-not (protocol? proto)
746 (throw (IllegalArgumentException.
747 (str proto " is not a protocol"))))
f47895ad » richhickey
2010-04-16 check that type does not already implement protocol interface when ex…
748 (when (implements? proto atype)
749 (throw (IllegalArgumentException.
750 (str atype " already directly implements " (:on-interface proto) " for protocol:"
751 (:var proto)))))
766b248f » richhickey
2009-11-11 first cut at protocols
752 (-reset-methods (alter-var-root (:var proto) assoc-in [:impls atype] mmap))))
18f1c963 » richhickey
2009-11-16 added extend-type and extend-class
753
754 (defn- emit-impl [[p fs]]
755 [p (zipmap (map #(-> % first keyword) fs)
756 (map #(cons 'fn (drop 1 %)) fs))])
757
758 (defn- emit-hinted-impl [c [p fs]]
759 (let [hint (fn [specs]
760 (let [specs (if (vector? (first specs))
761 (list specs)
762 specs)]
763 (map (fn [[[target & args] & body]]
764 (cons (apply vector (vary-meta target assoc :tag c) args)
765 body))
766 specs)))]
0cd1dc8a » Alexander Taggart
2011-10-08 Fix CLJ-845: Ignoring namespace portion of symbols used to name metho…
767 [p (zipmap (map #(-> % first name keyword) fs)
18f1c963 » richhickey
2009-11-16 added extend-type and extend-class
768 (map #(cons 'fn (hint (drop 1 %))) fs))]))
769
ba9b7924 » richhickey
2010-04-15 remove IDynamicType and type tags
770 (defn- emit-extend-type [c specs]
18f1c963 » richhickey
2009-11-16 added extend-type and extend-class
771 (let [impls (parse-impls specs)]
772 `(extend ~c
773 ~@(mapcat (partial emit-hinted-impl c) impls))))
774
775 (defmacro extend-type
776 "A macro that expands into an extend call. Useful when you are
777 supplying the definitions explicitly inline, extend-type
ba9b7924 » richhickey
2010-04-15 remove IDynamicType and type tags
778 automatically creates the maps required by extend. Propagates the
779 class as a type hint on the first argument of all fns.
18f1c963 » richhickey
2009-11-16 added extend-type and extend-class
780
ba9b7924 » richhickey
2010-04-15 remove IDynamicType and type tags
781 (extend-type MyType
18f1c963 » richhickey
2009-11-16 added extend-type and extend-class
782 Countable
783 (cnt [c] ...)
784 Foo
785 (bar [x y] ...)
786 (baz ([x] ...) ([x y & zs] ...)))
787
788 expands into:
789
ba9b7924 » richhickey
2010-04-15 remove IDynamicType and type tags
790 (extend MyType
18f1c963 » richhickey
2009-11-16 added extend-type and extend-class
791 Countable
792 {:cnt (fn [c] ...)}
793 Foo
794 {:baz (fn ([x] ...) ([x y & zs] ...))
795 :bar (fn [x y] ...)})"
c1c39162 » stuarthalloway
2010-04-29 metadata for :added
796 {:added "1.2"}
18f1c963 » richhickey
2009-11-16 added extend-type and extend-class
797 [t & specs]
798 (emit-extend-type t specs))
799
75cd0508 » richhickey
2009-11-16 added extend-protocol
800 (defn- emit-extend-protocol [p specs]
801 (let [impls (parse-impls specs)]
802 `(do
803 ~@(map (fn [[t fs]]
ba9b7924 » richhickey
2010-04-15 remove IDynamicType and type tags
804 `(extend-type ~t ~p ~@fs))
75cd0508 » richhickey
2009-11-16 added extend-protocol
805 impls))))
806
807 (defmacro extend-protocol
808 "Useful when you want to provide several implementations of the same
809 protocol all at once. Takes a single protocol and the implementation
810 of that protocol for one or more types. Expands into calls to
4d893250 » djpowell
2010-07-14 fixed extend-protocol doc
811 extend-type:
75cd0508 » richhickey
2009-11-16 added extend-protocol
812
813 (extend-protocol Protocol
4d893250 » djpowell
2010-07-14 fixed extend-protocol doc
814 AType
75cd0508 » richhickey
2009-11-16 added extend-protocol
815 (foo [x] ...)
816 (bar [x y] ...)
4d893250 » djpowell
2010-07-14 fixed extend-protocol doc
817 BType
75cd0508 » richhickey
2009-11-16 added extend-protocol
818 (foo [x] ...)
819 (bar [x y] ...)
820 AClass
821 (foo [x] ...)
822 (bar [x y] ...)
823 nil
824 (foo [x] ...)
825 (bar [x y] ...))
826
827 expands into:
828
829 (do
4d893250 » djpowell
2010-07-14 fixed extend-protocol doc
830 (clojure.core/extend-type AType Protocol
75cd0508 » richhickey
2009-11-16 added extend-protocol
831 (foo [x] ...)
832 (bar [x y] ...))
4d893250 » djpowell
2010-07-14 fixed extend-protocol doc
833 (clojure.core/extend-type BType Protocol
75cd0508 » richhickey
2009-11-16 added extend-protocol
834 (foo [x] ...)
835 (bar [x y] ...))
4d893250 » djpowell
2010-07-14 fixed extend-protocol doc
836 (clojure.core/extend-type AClass Protocol
75cd0508 » richhickey
2009-11-16 added extend-protocol
837 (foo [x] ...)
838 (bar [x y] ...))
839 (clojure.core/extend-type nil Protocol
840 (foo [x] ...)
841 (bar [x y] ...)))"
c1c39162 » stuarthalloway
2010-04-29 metadata for :added
842 {:added "1.2"}
75cd0508 » richhickey
2009-11-16 added extend-protocol
843
844 [p & specs]
845 (emit-extend-protocol p specs))
846
Something went wrong with that request. Please try again.