There is a ticket for metadata on functions:
https://www.assembla.com/spaces/clojure/tickets/94-GC--Issue-90---%09-Support-metadata-on-fns
So it seems this is a planned feature, but not implemented yet - due
to "Requires dealing with the with-meta copying issues for closures".
But as you mentioned, the macro version should suffice for your case?
(ns metatest
(:use clojure.test))
(def cascade-type-to-virtual-folder {:view "view"
:action "action"
:willow "willow"})
(defmacro path-to-function
"Calculates the path to a given view or action function. The result
is a path string, relative to the context root. If the function
defines :path meta-data, that it used, otherwise an appropriate path
is constructed within the virtual /view or /action folder."
[function]
`(let [fn-meta# (meta (var ~function))
type# (get fn-meta# :cascade-type)
folder# (get cascade-type-to-virtual-folder type#)
fn-path# (get fn-meta# :path)]
(println "function " ~function " meta" fn-meta#)
(when (or (nil? type#) (nil? folder#))
(println "Function is neither a view function nor an action
function."))
(cond
;; TODO: The user-supplied path may need some doctoring. It
should not start with or end
;; with a slash.
(not (nil? fn-path#)) fn-path#
;; Go from type to folder
true (str folder# "/" (ns-name (fn-meta# :ns)) "/" (name (fn-
meta# :name))))))
(defn valid-view-fn {:cascade-type :view} [])
(defn valid-action-fn {:cascade-type :action} [])
(defn pathed-action-fn {:cascade-type :action :path "do/something"}
[])
(defn pathed-view-fn {:cacade-type :view :path "show/something"} [])
(defn unknown-type-fn {:cascade-type :willow}[])
(defn no-cascade-type-fn [])
(println (path-to-function valid-view-fn))
On Aug 24, 1:41 am, Howard Lewis Ship <[email protected]> wrote:
> I keep running in circles with meta data on functions.
>
> This is my current understanding:
>
> Meta data for the function's name symbol is merged with any meta data
> provided as a map before the parameter decls.
>
> This combined meta-data is then applied to the Var that holds the function.
>
> However, it doesn't look like the function get the meta data. This is
> extra odd, because the AFn constructor takes a meta data map (though
> it throws UnsupportedOperationException if you attempt to use
> (with-meta).)
>
> I'd like to say I'm just mistaken, but I see this is my code:
>
> (defn path-to-function
> "Calculates the path to a given view or action function. The result
> is a path string,
> relative to the context root. If the function defines :path
> meta-data, that it used, otherwise
> an appropriate path is constructed within the virtual /view or
> /action folder."
> [function]
> (let [fn-meta (meta function)
> type (get fn-meta :cascade-type)
> folder (get cascade-type-to-virtual-folder type)
> fn-path (get fn-meta :path)]
> (debug "function %s, meta %s" function (ppstring fn-meta))
> (fail-if (or (nil? type) (nil? folder))
> (format "Function %s is neither a view function nor an action function."
> (qualified-function-name function)))
> (cond
> ;; TODO: The user-supplied path may need some doctoring. It
> should not start with or end
> ;; with a slash.
> (not (nil? fn-path)) fn-path
>
> ;; Go from type to folder
>
> true (str folder "/" (ns-name (fn-meta :ns)) "/" (name (fn-meta
> :name))))))
>
> and tests:
>
> (defn valid-view-fn {:cascade-type :view} [])
> (defn valid-action-fn {:cascade-type :action} [])
> (defn pathed-action-fn {:cascade-type :action :path "do/something"} [])
> (defn pathed-view-fn {:cacade-type :view :path "show/something"} [])
> (defn unknown-type-fn {:cascade-type :willow}[])
> (defn no-cascade-type-fn [])
>
> (deftest test-path-to-function
> (are (= (path-to-function _1) _2)
> valid-view-fn "view/cascade.test-path-map/valid-view-fn"
> valid-action-fn "action/cascade.test-path-map/valid-action-fn"
> pathed-action-fn "do/something"
> pathed-view-fn "show/something"))
>
> Execution:
>
> Testing cascade.test-path-map
> [DEBUG] cascade.path-map function
> cascade.test_path_map$valid_view_fn__...@eedabc, meta nil
>
> I can make my test work by passing #'valid-view-fn instead of valid-view-fn:
>
> Testing cascade.test-path-map
> [DEBUG] cascade.path-map function
> #'cascade.test-path-map/valid-view-fn, meta {:ns #<Namespace
> cascade.test-path-map>,
> :name valid-view-fn,
> :file "cascade/test_path_map.clj",
> :line 42,
> :arglists ([]),
> :cascade-type :view}
>
> But this isn't what I want.
>
> I think I can get the syntax I like using a macro, but I don't
> understand why a Fn, which implements the IMeta interface (because it
> extends from the Obj base class), doesn't have access to its own meta
> data. This would be useful just for name, line, arglists, etc., not to
> mention user-added meta data such as :cascade-type.
>
> My work around may be to use a macro to access the Var for the meta
> data ... I just don't understand the reasoning behind the nil meta
> data for functions.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---