Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure by
(def a) destroys #'a metadata, check this:


(def ^:mykey a 1)

(meta #'a)              ;; ok, :mykey is present

(let [v (def a)]
   [(meta v)            ;; NO :mykey present, metadata destroyed
    (identical? v #'a)  ;; true, we are talking of the same var
   ])

(meta #'a)              ;; NO :mykey present


If this is not a bug but a "feature", then we have at least two problems:

1- The def special form documentation doesn't state this behaviour at all, it needs to be clarified. With the current documentation it seems as doing a def with no init supplied will not make any side-effect at all, and this is not true for the var metadata.

2- defmulti uses this form to lookup the var and check if it already binds to a MultiFn, if that is the case then defmulti does nothing... but it really does something, defmulti will destroy the original var metadata in the (supposedly non-destructive) check. This is the involved defmulti fragment:


(let [v# (def ~mm-name)]
  (when-not (and (.hasRoot v#) (instance? clojure.lang.MultiFn (deref v#)))
   ...

6 Answers

0 votes
by

Comment made by: alexmiller

I think this is mostly a dupe of CLJ-1148 but I'll leave it as it states the specific problem more precisely.

0 votes
by

Comment made by: nahuel

Alex Miller: It seems CLJ-1148 is an special case where this problem shows, but the patches in CLJ-1148 only fixes the issues for {{defonce}}, not generally for {{def}}, not for {{defmulti}} and not clarifies this behaviour in the {{def}} special form documentation.

0 votes
by

Comment made by: stu

I am pretty sure we have been here before, and decided that {{def}} is working as desired. (If anybody can find the thread/ticket please add a link.) I think this should be a doc enhancement.

If the behavior of {{defmethod}} is a separate bug, please make a separate ticket for that, showing an example problem.

0 votes
by

Comment made by: jafingerhut

CLJ-1213 might be related, but it doesn't mention metadata, only (def foo) without init value given.

0 votes
by

Comment made by: seancorfield

If Stuart is right that this is considered the correct behavior for {{def}} then {{defonce}} should not use (def ~name) -- per CLJ-1148. Could we get a decision once and for all and then reject this issue if the behavior is as designed? Or do we want a patch to update the docstring to make the metadata issue clear?

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-1446 (reported by nahuel)
...