Share your thoughts in the 2021 Clojure Community Survey!

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

+1 vote
in ClojureScript by
edited by

I'm attempting to set some arglists metadata on vars. However the arglists are not preserved when accessing the metadata.

tmp ❯❯❯ clj -A:cljs -m cljs.main -re node -r
ClojureScript 1.10.773
cljs.user=> (def ^{:arglists '[[x]]} thing 3)
#'cljs.user/thing
cljs.user=> (:arglists (meta #'thing))
()

This is preserved in clojure:

tmp ❯❯❯ clj
Clojure 1.10.1
user=> (def ^{:arglists '[[x]]} thing 3)
#'user/thing
user=> (:arglists (meta #'thing))
[[x]]

In cljs it also will preserve non-arglists metadata:

cljs.user=> (def ^{:foo '[[x]]} thing 3)
#'cljs.user/thing
cljs.user=> (:foo (meta #'thing))
(quote [[x]])

Wondering if this is necessary behavior due to the unique nature of "vars" in ClojureScript or if a bug.

Edit:
seems to be a bug. Jira ticket: https://clojure.atlassian.net/browse/CLJS-3277

1 Answer

0 votes
by

The root of the problem is that CLJS doesn't have reified vars at runtime. The metadata is actually preserved and accessible on the compiler side of things (in CLJ) but seems to have some bad merge logic which removes it when outputing the var meta.

I'd strongly recommend not doing any var based "meta" programming in CLJS since there will be many more issues like this that don't line up with Clojure. Var instances are recreated each time and cannot be manipulated like you can in CLJ.

user=> (def ^{:arglists '[[x]]} thing 3)
#'user/thing
user=> (identical? #'thing #'thing)
true

vs CLJS

cljs.user=> (def ^{:arglists '[[x]]} thing 3)
#'cljs.user/thing
cljs.user=> (identical? #'thing #'thing)
false
...