Friday, October 03, 2008

Clojure metadata

I watched the video of Rich Hickey's talk about Clojure at the Boston Lisp group this week and was very impressed by his design. One of the features I've been mulling is Clojure's notion of metadata: every value can be associated with extra associative data. That data does not affect the value's behavior under the standard equality predicate, so in some sense it can be seen as "invisible." This is kind of like JavaScript objects' arbitrarily extensible property tables, except for the very important difference that it's immutable. So you can create a value that's more or less equivalent to another (it is distinguishable by identical?, but use of that predicate is discouraged) but with some extra information on the side.

The first use I immediately thought of for this is when you're writing a compiler or interpreter that has AST nodes and you want to save source location information. This information shouldn't affect AST equality. Clojure metadata sounds like it could be a good way to separate that concern.

I think it's confusing, at least for me, that Rich describes metadata as not being "part of the value"--where I come from, a value is the result of evaluating an expression. When you evaluate (with-meta v m) you do get a new value that is associated with metadata m. What Rich is saying is that the metadata is not contained within v. At first when he said it wasn't part of the value, I thought "that sounds brittle." But if I've understood it, a more accurate description might be that values in Clojure may carry with them an extra associative map that doesn't affect their printed representation or their equality.

4 comments:

John Clements said...

can every value have such metadata? If so, it sounds like memoization is toast, along with many other useful lines of thinking based on value equality.

Paul Steckler said...

(if (u-would-like-fries-with-that)
  (with-meta (mk-order) 'fries)
  (mk-order))

-- Paul

Anonymous said...

Credit where credit is due: these are "Dual Values" in the sense of Clifford (1873) who introduced them, with a type constraint (Dual Numbers), in the formulation of bi-quaternions.

Mike Hinchey said...

Not all values can have metadata, only "Symbols and collections support metadata". So far, I've only seen it used for symbols: to add doc strings, compiler info like private, test and invariant functions, and AST like you said. Memoization works because the metadata is not part of the value.

-Mike