Skip to content

Commit abcd7e1

Browse files
committed
add arglists and doc metadata to deftype/defrecord constructor fns
Matches Clojure behavior where (meta #'->Foo) has :arglists and :doc. Also fixes deftype constructor to use positional args instead of varargs, enforcing correct arity like Clojure does.
1 parent 8b2a981 commit abcd7e1

File tree

3 files changed

+23
-10
lines changed

3 files changed

+23
-10
lines changed

src/sci/impl/deftype.cljc

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,11 @@
174174
impls)))
175175
protocol-impls)]
176176
(emit-deftype rec-type record-name factory-fn-sym
177-
`(defn ~factory-fn-sym [& args#]
178-
(sci.impl.deftype/->type-impl '~rec-type ~record-name ~record-name (zipmap ~(list 'quote fields) args#)))
177+
`(defn ~(with-meta factory-fn-sym
178+
{:doc (str "Positional factory function for class " rec-type ".")
179+
:arglists (list fields)})
180+
~fields
181+
(sci.impl.deftype/->type-impl '~rec-type ~record-name ~record-name (zipmap ~(list 'quote fields) ~fields)))
179182
protocol-impls))))
180183

181184
(defn deftype-macro
@@ -276,7 +279,10 @@
276279
`#{~@(map (fn [p] (list 'deref (:var p))) protocols)}
277280
`#{})]
278281
(emit-deftype rec-type record-name factory-fn-sym
279-
`(defn ~factory-fn-sym [~@fields]
282+
`(defn ~(with-meta factory-fn-sym
283+
{:doc (str "Positional factory function for class " rec-type ".")
284+
:arglists (list fields)})
285+
[~@fields]
280286
(~constructor-sym {:methods (hash-map ~@method-entries)
281287
:fields (hash-map ~@field-entries)
282288
:protocols ~protocols-form}))))
@@ -348,8 +354,11 @@
348354
impls)))
349355
protocol-impls)]
350356
(emit-deftype rec-type record-name factory-fn-sym
351-
`(defn ~factory-fn-sym [& args#]
352-
(sci.impl.deftype/->type-impl '~rec-type ~record-name ~record-name (zipmap ~(list 'quote fields) args#)))
357+
`(defn ~(with-meta factory-fn-sym
358+
{:doc (str "Positional factory function for class " rec-type ".")
359+
:arglists (list fields)})
360+
~fields
361+
(sci.impl.deftype/->type-impl '~rec-type ~record-name ~record-name (zipmap ~(list 'quote fields) ~fields)))
353362
protocol-impls)))]
354363
(if top-level?
355364
(types/->EvalForm result)

src/sci/impl/records.cljc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,14 @@
342342
ext# (merge ext#)
343343
meta# (with-meta meta#)))))
344344

345-
(defn ~factory-fn-sym
345+
(defn ~(with-meta factory-fn-sym
346+
{:doc (str "Positional factory function for class " rec-type ".")
347+
:arglists (list fields)})
346348
(~fields
347349
(~constructor-fn-sym ~@fields nil nil)))
348-
(defn ~map-factory-sym [m#]
350+
(defn ~(with-meta map-factory-sym
351+
{:doc (str "Factory function for class " rec-type ", taking a map of keywords to field values.")})
352+
[m#]
349353
(sci.impl.records/->record-impl '~rec-type
350354
~record-name
351355
~key-set

test/sci/defrecords_and_deftype_test.cljc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,12 @@
191191
#?(:cljs (def Exception js/Error))
192192

193193
(deftest deftype-test
194-
(is (= 1 (tu/eval* "(defprotocol GetX (getX [_])) (deftype Foo [x y] GetX (getX [_] x)) (getX (->Foo 1)) " {})))
194+
(is (= 1 (tu/eval* "(defprotocol GetX (getX [_])) (deftype Foo [x y] GetX (getX [_] x)) (getX (->Foo 1 2)) " {})))
195195
(let [prog "(deftype Foo [a b]) (let [x (->Foo :a :b)] [(.-a x) (.-b x)])"]
196196
(is (= [:a :b] (tu/eval* prog {}))))
197197
(is
198198
(= 10
199-
(tu/eval* (str/replace "(defprotocol IFoo (setField [_]) (getField [_])) (deftype Foo [^:volatile-mutable a] IFoo (setField [_] (set! a 10)) (getField [_] a)) (getField (doto (->Foo) (setField)))"
199+
(tu/eval* (str/replace "(defprotocol IFoo (setField [_]) (getField [_])) (deftype Foo [^:volatile-mutable a] IFoo (setField [_] (set! a 10)) (getField [_] a)) (getField (doto (->Foo nil) (setField)))"
200200
"^:volatile-mutable" #?(:clj "^:volatile-mutable"
201201
:cljs "^:mutable")) {})))
202202
(is (= [1 2 2]
@@ -234,7 +234,7 @@
234234
(is (= "dude" (tu/eval* "(deftype Dude [] Object (toString [_] \"dude\")) (str (->Dude))" {})))
235235
#?(:clj (is (= [true false] (tu/eval* "(deftype Dude [x] Object (toString [_] (str x)) (equals [this other] (= (str this) (str other)))) [(= (->Dude 1) (->Dude 1)) (= (->Dude 1) (->Dude 2))]" {}))))
236236
#?(:clj (is (true? (tu/eval* "(deftype Dude [x] Object (hashCode [_] 1))
237-
(deftype Dude2 [x]) (and (= 1 (hash (Dude. 1337))) (not= 1 (hash (Dude2.))))" {})))))
237+
(deftype Dude2 [x]) (and (= 1 (hash (Dude. 1337))) (not= 1 (hash (Dude2. nil))))" {})))))
238238

239239
(deftest equiv-test
240240
(let [prog "(defrecord Foo [a]) (defrecord Bar [a]) [(= (->Foo 1) (->Foo 1)) (= (->Foo 1) (->Bar 1)) (= (->Foo 1) {:a 1})]"]

0 commit comments

Comments
 (0)