Question

As a clojure beginner, I am reading clojure code to get myself familiar with Clojure's grammar. Below code snippet is a function in Ring project

(defn- request-context
"Create an UploadContext object from a request map."
{:tag UploadContext}
[request encoding]
(reify UploadContext
(getContentType [this]       (get-in request [:headers "content-type"]))
(getContentLength [this]     (or (req/content-length request) -1))
(contentLength [this]        (or (req/content-length request) -1))
(getCharacterEncoding [this] encoding)
(getInputStream [this]       (:body request))))

what is not clear to me is the line

{:tag UploadContext}

if review a clojure function's definition

(defn function-name doc-string? attr-map? [parameter-list]
conditions-map?
(expressions))

I guess (but not sure) the map should be the "attr-map?". But what is a "attr-map?"? I googled and cannot find good explanations.

any examples or links to introduce the "attr-map?" will be appreciated. I also would like to know how the attr-map is used in the code I pasted.

Was it helpful?

Solution

Passing an (optional) attr-map? to defn is a shorthand way of adding metadata to a function's var.

Metadata might include entries such as :tag (runtime return type), :doc (a documentation string) and :private (to indicate if the var is private to a namespace). Additional pieces of metadata can also be attached there too, but should be used for data that is "orthogonal to the logical value of the data" (quote from http://clojure.org/functional_programming)

(defn greet {:tag String :other-meta-data 5} [name] (format "Hello, %s" name))

(meta #'f)
;=> {:arglists ([name]), :ns #<Namespace user>, :name f, :end-column 8, :column 1,
     :line 4 :other-meta-data 5, :file "NO_SOURCE_FILE", :end-line 4, 
     :tag java.lang.String}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top