On Apr 15, 2009, at 13:31, Rich Hickey wrote: > That's an open question. There are many reasons it is better as a > normal key. The arguments for being metadata are: > > It allows for things other than maps to have 'types' > It doesn't impact equality > It doesn't appear as a 'field' to other code > > Advantages to having it be a map key/attribute: > > That's really what type/class is, another attribute, thus only things > that have attributes (maps) should have it. > It will impact equality* > It will appear as a 'field' to other code, in particular things like > Datalog > > * - a key issue here is that only exact type equality is supported.
I found a couple of situations where a third choice is preferable: put type-related information both in the metadata and in the map itself. In all these situations, the main reason is the impact on equality, and usually the type information in the metadata is not the same as the type information in the map itself. As an example, take algebraic data types as defined in clojure.contrib.types. A simple binary tree structure can be defined with (defadt ::tree empty-tree (leaf value) (node left-tree right-tree)) Values of this type are represented as maps in which the value associated with :clojure.contrib.types/tag is the constructor (`empty- tree, `leaf, or `node), with the :type in the metadata being ::tree. This double labelling makes sure that all tree values are recognized as being of the same type in dispatching, but also that equality tests take into account the constructor in addition to its arguments. Note that there is no need here to have the type ::tree as part of the value, as it is impossible to create two different types with identical constructor names in the same namespace (the constructor names are interned via def) and both the type tag and the constructor names are namespace qualified. The only way to make a data item equal to a ::tree value would be to construct explicitly a map containing the namespace-qualified key :clojure.contrib.types/tag, which I would call a malicious attempt to break something. In this example, the type information for equality is more specific than the type information for dispatching, but there are also situations in which the opposite is required. Both are simple to implement in Clojure. Konrad. --~--~---------~--~----~------------~-------~--~----~ 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 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 -~----------~----~----~----~------~----~------~--~---