On May 8, 2014, at 8:34 AM, Pascal Germroth <funkyco...@gmail.com> 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 clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
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 clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to