Fork me on GitHub
#clojure-dev
<
2021-03-14
>
ikitommi12:03:56

Is there a reason why vectors can be used as keys in metadata when defined via ^ reader macro? these all work:

(meta (with-meta {} {:int true}))
; => {:int true}

(meta ^{:int true} {})
; => {:int true}

(meta ^:int {})
; => {:int true}
here, the last doesn’t:
(meta (with-meta {} {[:tuple :int] true}))
; => {[:tuple :int] true}

(meta ^{[:tuple :int] true} {})
; => {[:tuple :int] true}

(meta ^[:tuple :int] {})
; =throws=> Metadata must be Symbol,Keyword,String or Map

borkdude12:03:31

@ikitommi What do you expect the metadata to be?

borkdude12:03:43

{[:tuple :int] true} ?

ikitommi12:03:02

yes, same as the second (working) example.

cgrand13:03:45

I believe shorthand syntax has been allocated parsimoniously as needed. So keyword shorthand was for opt-in flags and not a default transformation “if not a map or a type (sym/string) turn x in {x true}”.

andy.fingerhut13:03:24

Yes, the general case of metadata is always a map. The ^:kw is just a light syntactic sugar that is replaced with a map {:kw true} and only for keywords. (Well, there is also ^Classname -> {:tag Classname})

ikitommi14:03:10

ok, thanks. String also seems to write :tag:

(meta ^int? {}) ; => {:tag #object[clojure.core$int_QMARK_"]}
(meta ^:int {}) ; => {:int true}
(meta ^"int" {}) ; => {:tag "int"}
(meta ^{:type :int} {}) ; => {:type :int}
(meta ^Integer {}) ; => {:tag java.lang.Integer}

jjttjj15:03:14

I believe that's necessary to tag things when their class name is an invalid symbol, such as native arrays like

"[Ljava.lang.String;"

cgrand15:03:02

Yes it’s the reason.