2011-04-08 16 views
15

Decir que tengo el siguiente código:¿Cómo encuentro dinámicamente metadatos para una función de Clojure?

 
(defn ^{:graph-title "Function 1"} func-1 
    [x] 
    (do-something-with x)) 

(defn get-graph-title 
    [func] 
    (str 
    ((meta func) :graph-title))) 

me esperaba esto para volver "Función 1", pero se vuelve nula. Creo que esto se debe a la siguiente diferencia, que yo 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 explicar esto a mí?

Respuesta

18

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" 
+4

O simplemente use la definición actual y do (get-graph-title # 'func-1) –

2

Los metadatos se especifica en el símbolo func-1 en su código fuente se copia en el var llamada func-1 por la forma especial def. Consulte la documentación de definición en http://clojure.org/special_forms

Al evaluar func-1 donde eso es un símbolo unido a un var, se 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í mismo no recibe automáticamente los metadatos especificados manualmente en el símbolo/var.

Por lo tanto, la información que desea no figura en absoluto en la función. Está en la var, y debes especificar que realmente quieres el var func-1 en vez de su valor. Eso es lo que (var func-1), y el atajo equivalente # 'func-1 hace.

30

Hay metadatos sobre la función func-1, los metadatos en el Var #'func-1 y metadatos en el símbolo'func-1. La macro del lector de Clojure ^ agrega metadatos al símbolo, en tiempo de 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 eran compatibles con los metadatos. En Clojure 1.2, que hacen, y defn también copia alguna norma Var metadatos para 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 la actualidad Clojure 1.3 instantáneas, defn no copia los metadatos de 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 usted desea conseguir en los metadatos de una definición, que desea metadatos en el Var.

+0

La respuesta de Leonel estuvo más cerca de lo que estaba buscando, pero gracias por la explicación, aclara mucho las cosas. – funkymunky

Cuestiones relacionadas