On May 8, 2014, at 8:34 AM, Pascal Germroth <[email protected]> wrote:
> I'm trying to attach metadata to some values (not the vars holding them).
> I thought ^{x} y was the same as (with-meta y {x}),
There was a recent thread about this here.
https://groups.google.com/forum/#!searchin/clojure/metadata$20reader/clojure/iyYwwWPgv2U/xh-4SonzudkJ
^ is a reader macro that applies metadata to a target. The target is the result
of reading the form that immediately follows the metadata form. ^ operates at
read time, after the target form is read, but before it is evaluated. There are
some subtleties in your example that make exactly what's happening not obvious.
As a tool for understanding, read-string on a string can help by giving you
visibility into the reader's operation alone. This is in contrast to the REPL
where the result you see is after both read and eval have completed.
> but while it works for f2/f4, f1's metadata is nowhere to be found, while f3
> works as expected:
>
> (def f1 "doc" ^{:x 1} (partial inc))
> (meta f1) ; nil, unexpected
> (meta #'f1) ; contains :doc, but not :x, as expected
The target form in this case is "(partial inc)". Checking (read-string
"(partial inc)") confirms that the reader returns a list containing two
symbols. The reader macro ^ applied the metadata to that list. The evaluator
then evaluated that list by invoking the function bound to the var
clojure.core/partial. That function has no access to the metadata on the list
that the reader read. After evaluation there is no longer any reference to that
list or its metadata. They are both dropped.
> (def f2 "doc" ^{:x 2} #(inc %))
> (meta f2) ; {:x 2}, as expected
> (meta #'f2) ; contains :doc, but not :x, as expected
The target form in this case is "#(inc %)". (read-string "#(inc %)") shows that
the reader returns a list like this (containing a symbol, a vector, and a list):
(fn* [p1__1925#] (inc p1__1925#))
The name fn* is an implementation detail, you can think of it as fn.
Because fn is a special form, it does have access to the list that was returned
by the reader and the metadata on it. One thing fn does is transfer the
metadata on that list to the function object it creates. That's why (meta f2)
works as you expected.
There was no metadata applied to the symbol f2. If there had been it would have
been transferred by the special form def to the var it created. Your
expectation here is probably based on the action of the defn macro which
transfers metadata in a defn form to the var it creates.
> (def f3 "doc" (with-meta (partial inc) {:x 3}))
> (meta f3) ; {:x 3}
with-meta operates after (partial inc) is evaluated so it applies the metadata
to the function object returned by partial.
> (def f4 "doc" (with-meta #(inc %) {:x 4}))
> (meta f4) ; {:x 4}
same here.
--Steve
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
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
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.