function - ¿Cómo encuentro dinámicamente los metadatos para una función de Clojure?
metadata clojure-contrib (3)
Hay metadatos en la función func-1
, metadatos en Var #''func-1
y metadatos en el símbolo ''func-1
. La macro del lector de Clojure ^
agrega metadatos al símbolo , en el momento de la lectura. La macro defn
copia los metadatos del símbolo al Var , en tiempo de compilación.
Antes de Clojure 1.2, las funciones no admitían metadatos. En Clojure 1.2, lo hacen, y defn
también copia algunos metadatos Var estándar a la función :
Clojure 1.2.0
user=> (defn ^{:foo :bar} func-1 [] nil)
#''user/func-1
user=> (meta func-1)
{:ns #<Namespace user>, :name func-1}
user=> (meta #''func-1)
{:foo :bar, :ns #<Namespace user>, :name func-1, ...
Sin embargo, en las instantáneas actuales de Clojure 1.3, defn
no copia ningún metadato a la función:
Clojure 1.3.0-master-SNAPSHOT
user=> (defn ^{:foo :bar} func-1 [] nil)
#''user/func-1
user=> (meta func-1)
nil
user=> (meta #''func-1)
{:foo :bar, :ns #<Namespace user>, :name func-1, ...
En general, si desea obtener los metadatos de una definición, desea metadatos en el Var .
Digamos que tengo el siguiente código:
(defn ^{:graph-title "Function 1"} func-1 [x] (do-something-with x)) (defn get-graph-title [func] (str ((meta func) :graph-title)))
Espero que esto devuelva "Función 1", pero devuelve nil. Creo que esto se debe a la siguiente diferencia, que no comprendo totalmente:
(meta func-1) => {:ns some-ns-info, :name func-1} (meta #''func-1) => {:ns some-ns-info, :name func-1, :graph-title "Function 1"}
¿Puede alguien explicarme esto?
Los metadatos que especifique en el símbolo func-1 en su código fuente se copian a la var llamada func-1 mediante la forma especial de def. Consulte la documentación para la definición en http://clojure.org/special_forms
Cuando evalúa func-1
donde es un símbolo vinculado a una var, obtiene el valor de la var (que es el objeto de la función en este caso). Ver http://clojure.org/vars
El objeto de función en sí no recibe automáticamente los metadatos especificados manualmente en el símbolo / var.
Por lo tanto, la información que desea no está en la función en absoluto. Está en la var, y debe especificar que realmente desea la var func-1
en lugar de su valor. Eso es lo que hace (var func-1), y el atajo equivalente # ''func-1 lo hace.
Los metadatos se adjuntan a la var, no a la función.
Por lo tanto, para obtener el título del gráfico, debe obtener la entrada :graph-title
del meta de la var. ¿Cómo te gustan tus macros?
(defmacro get-graph-title
[func]
`(:graph-title (meta (var ~func))))
(get-graph-title func-1)
=> "Function 1"