Placement of metadata in defn

9 views
Skip to first unread message

Paul Drummond

unread,
Oct 23, 2008, 9:11:28 AM10/23/08
to Clojure
I am a bit puzzled by how metadata seems to behave differently
depeding on where it's used and whether #^ is included or not:

(defn #^{:doc "doc"} my-fn ([x] x)) ;;Works
(defn {:doc "doc"} my-fn ([x] x)) ;;Error: Second argument to def
must be a Symbol
(defn my-fn [x] x #^{:doc "doc"}) ;;Error: Unmatched delimiter: )
(defn my-fn ([x] x) {:doc "doc"}) ; ;;Works

Can anyone help me understand this please?

Cheers,
Paul.



Rich Hickey

unread,
Oct 23, 2008, 9:21:25 AM10/23/08
to Clojure


On Oct 23, 9:11 am, Paul Drummond
Sure. #^ is reader syntax for metadata. It adorns the following thing
read, it is not a thing unto itself. So,

#^{:doc "doc"} my-fn

is read all together as one thing, a symbol named my-fn, having the
metadata map {:doc "doc"}. Putting #^{:doc "doc"} at the end of a
list is metadata adorning nothing, and thus an error.

defn's internal syntax supports map literal forms, which are added as
metadata on the resulting var, but are not metadata literals in the
source.

The important thing to understand is how the reader works first,
producing a data structure which is them processed by any macros or
the compiler.

Read as list of symbol symbol list:
(defn #^{:doc "doc"} my-fn ([x] x))

Read as list of symbol map symbol list:
(defn {:doc "doc"} my-fn ([x] x))

Rich

mb

unread,
Oct 23, 2008, 9:28:44 AM10/23/08
to Clojure
Hi Paul,

On 23 Okt., 15:11, Paul Drummond
<paul.drummond.webm...@googlemail.com> wrote:
> I am a bit puzzled by how metadata seems to behave differently
> depeding on where it's used and whether #^ is included or not:

AFAIU, #^ attaches the given map to the thing read.

> (defn #^{:doc "doc"}  my-fn ([x] x))
> ;;Works
Attaches {:doc "doc"} to the metadata of the symbol my-fn.

> (defn {:doc "doc"}  my-fn ([x] x))
> ;;Error: Second argument to def must be a Symbol
Obviously #^ is missing, hence the map is passed on to defn.
Defn expects a Symbol not a Map. => *meep*

> (defn my-fn [x] x #^{:doc "doc"})
> ;;Error: Unmatched delimiter: )
Since #^ attaches to the next thing read and there is
nothing following the reader screws up in some way.

> (defn my-fn ([x] x) {:doc "doc"})
> ;;Works
This is the syntax of defn, I believe. What ever map
you pass at the end of the definition is added to the
meta-data.

> Can anyone help me understand this please?
I'm not sure understand this meta-data stuff myself...

Sincerely
Meikel

Paul Drummond

unread,
Oct 23, 2008, 10:48:11 AM10/23/08
to Clojure
Thanks guys, I get it now. I was forgetting that #^ attaches to the
next thing read, it makes sense now!





Reply all
Reply to author
Forward
0 new messages