Metadata

The Wikipedia entry on metadata[17] begins by saying that metadata is “data about data.” That is true but not usably specific. In Clojure, metadata is data that is orthogonal to the logical value of an object. For example, a person’s first and last names are plain old data. The fact that a person object can be serialized to XML has nothing to do with the person and is therefore metadata. Likewise, the fact that a person object is dirty and needs to be flushed to the database is metadata.

The Clojure language itself uses metadata in several places. For example, vars have a metadata map containing documentation, type information, and source information. Here is the metadata for the str var:

 (meta #​'str​)
 {:ns #object[clojure.lang.Namespace 0x62ccf439 ​"clojure.core"​],
  :name str,
  :added ​"1.0"​,
  :file ​"clojure/core.clj"​,
  :line 544,
  :column 1,
  :tag java.lang.String,
  :arglists ([] [x] [x & ys]),
  :doc
 "With no args, ...[etc]"​}

Some common metadata keys and their uses are shown in the following table.

Key

Used For

Key

Used For

:ns

Namespace

:column

Source column number

:name

Local name

:tag

Expected argument or return type

:added

Version this function was added

:arglists

Parameter info used by doc

:file

Source file

:doc

Documentation used by doc

:line

Source line number

:macro

True for macros

Much of the metadata on a var is added automatically by the Clojure compiler. To add your own key/value pairs to a var, use the metadata reader macro:

 ^metadata form

For example, you could create a simple shout function that upcases a string and then document that shout both expects and returns a string, using the :tag key:

 ; see also shorter form below
 (​defn​ ^{:tag String} shout [^{:tag String} s] (clojure.string/upper-case s))
 -> #​'user/shout

You can inspect shout’s metadata to see that Clojure added the :tag:

 (meta #​'shout​)
 -> {:arglists ([s]),
 :ns #object[clojure.lang.Namespace 0x284c1da6 ​"user"​],
 :name shout,
 :line 32,
 :column 1,
 :file ​"NO_SOURCE_PATH"​,
 :tag java.lang.String}

You provided the :tag, and Clojure provided the other keys. The :file value NO_SOURCE_PATH indicates that the code was entered at the REPL.

Because :tag metadata is so common, you can also use the short-form ^Classname, which expands to ^{:tag Classname}. Using the shorter form, you can rewrite shout as follows:

 (​defn​ ^String shout [^String s] (clojure.string/upper-case s))
 -> #​'user/shout

If you find the metadata disruptive when you’re reading the definition of a function, you can place the metadata last. Use a variant of defn that wraps one or more body forms in parentheses, followed by a metadata map:

 (​defn​ shout
 ([s] (clojure.string/upper-case s))
 {:tag String})
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.239.214