Monday, 12 January 2009

Metadata in Clojure

Each Clojure function can have a documentation string associated with it. This must be declared immediately before the parameters, for example:


(defn foo-baz
"Foo-bazes bar"
[bar]
(+ bar 77))

user> (doc foo-baz)
-------------------------
user/foo-baz
([bar])
Foo-bazes bar


This is actually short hand for:


(defn #^{:doc "Foo-bazes bar"} foo-baz
[bar]
(+ bar 77))


#^ indicates to the reader that the following map is metadata to be associated with the next element read. You can use this to document def'd values too (e.g. (def #^{:doc "This is the value x"} x).

Metadata is associated with symbols or collections, and meta can be used to view the associated values. Initially I was doing (meta count) and expecting it to come up with the details about agent. This is wrong because count is an instance of the function, whereas what I need to pass as an argument to meta is the symbol associated with the function e.g.


user> (meta count)
nil
user> (meta #'count) ; ^#'count also works (^ is a reader character to get the metadat)
{:ns #, :name count, :doc "Returns the number of items in the collection.
(count nil) returns\n 0. Also works on strings, arrays, and Java Collections and Maps",
:arglists ([coll]), :line 842, :file "core.clj"}


Note how extra metadata has arrived when it was compiled, including the line number of the original file, name space etc.

There are many cool potential applications of metadata in Clojure, though I haven't seen any implemented yet!:

Labels: ,


This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]