On Dec 2, 4:30 am, Kei Suzuki <[EMAIL PROTECTED]> wrote:
> Hi,
>
> Whenever a seq form is preceded by #^metadata, the metadata is ignored
> or only {:line n} is associated with.
>
> For example, these return the metadata as expected:
>
> (meta (with-meta '(1) {:v 1}))
> (meta (with-meta (quote (1)) {:v 1}))
> (meta (with-meta (list 1) {:v 1}))
> (meta (with-meta (vector 1) {:v 1}))
> (meta (with-meta (hash-map :a 1) {:v 1}))
> (meta (with-meta (set [1]) {:v 1}))
>
> But none of these equivalents work and either nil or {:line n} is
> returned:
>
> (meta #^{:v 1} '(1))
> (meta #^{:v 1} (quote (1)))
> (meta #^{:v 1} (list 1))
> (meta #^{:v 1} (vector 1))
> (meta #^{:v 1} (hash-map :a 1))
> (meta #^{:v 1} (set [1]))
>
> However, these work (because what's following is a non-seq form):
>
> (meta #^{:v 1} [1])
> (meta #^{:v 1} {:a 1})
> (meta #^{:v 1} #{1})
>
> Looking at the Clojure source code, it looks like
> LispReader.MetaReader does associate the metadata to the seq form but
> it's ignored when the seq form is analyzed by Compiler.analyzeSeq.
>
> Is this by design?
First and most important:
#^ is not sugar for with-meta. It does not expand into a call to with-
meta. They are not equivalent.
#^ is a way to place metadata on the data objects read by the reader.
Once read by the reader, the compiler can utilize metadata on the
forms. Currently the primary use is to convey type hints. Macros can
interpret metadata on forms they are passed for various purposes. This
is all about code-as-data, not a runtime thing.
Since a list is interpreted by the compiler as a call, any metadata on
the list is searched for type hints. There is no other meaning for
metadata on a list as far as the compiler is concerned. Ditto metadata
on symbols.
Since vector and map literals are interpreted by the compiler as
evaluated data, it evaluates any metadata on the literal to become
metadata on the value:
(set! *print-meta* true)
(quote #^{:a (+ 1 2)} [1 2 (+ 3 4)])
=> #^{:a #^{:line 17} (+ 1 2)} [1 2 #^{:line 17} (+ 3 4)] ;what was
read, vector + meta
#^{:a (+ 1 2)} [1 2 (+ 3 4)]
=> #^{:a 3} [1 2 7] ;evaluated vector + meta
Metadata on a seq form is not ignored:
(set! *print-meta* false)
(set! *warn-on-reflection* true)
(def x "foo")
(.length (identity x))
=> Reflection warning, line: 26 - reference to field length can't be
resolved.
=> 3
=> (.length #^String (identity x))
=> 3
So #^ allows the reader to read data with metadata on it.
Interpretation of forms that have metadata is up to the compiler.
Bottom line:
#^ is not sugar for with-meta. It does not expand into a call to with-
meta.
Rich
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---