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

0 votes
in ClojureScript by
edited by

When storing a function in a var's metadata, is behaves counterintuitively (at least to me).
Is this a bug or the intended behavior? If the latter, what is the reasoning?

Given the following def:

(def
  ^{:fn-in-meta (fn [a b] (+ a b))}
  my-var
  :value)

In Clojure things work as expected, one can get the function out of the metadata and it is still a regular function:

  ; clj
(-> #'my-var
    meta
    :fn-in-meta)
;; => #function[myns/fn--27244]

; clj
(-> #'my-var
    meta
    :fn-in-meta
    type)
;; => myns$fn__27244

In clojurescript however, doing the same seems to result in some semi-compiled state that looks similar to a macroexpansion.

 ; cljs
(-> #'my-var
    meta
    :fn-in-meta)
;; => (fn [a b] (+ a b))

; cljs
(-> #'my-var
    meta
    :fn-in-meta
    type)
;; => cljs.core/List

Finally, note that adding metadata to another object, such as a vector behaves normally in noth languages.

 ; cljs
(->> {:fn-in-meta (fn [a b] (+ a b))}
     (with-meta [])
     meta
     :fn-in-meta
     type)
;; => #object[Function]


; clj
(->> {:fn-in-meta (fn [a b] (+ a b))}
     (with-meta [])
     meta
     :fn-in-meta
     type)
;; => myns$eval27282$fn__27283

1 Answer

+1 vote
by
selected by
 
Best answer

It has nothing to do with macroexpansion. Metadata on vars in CLJS is not evaluated, that's it. Why exactly - I don't know. There's some discussion at https://clojure.atlassian.net/browse/CLJS-2390

Your example with vectors works because the function form is mentioned not in the metadata position of the def macro, so its evaluation happens in a regular way.

...