2012-04-22 10 views
11

Estoy creando una aplicación web noir, y necesito crear dinámicamente nuevas vistas y modelos. He estado siguiendo los ejemplos de noir, en los cuales la vista y el controlador de un recurso tienen espacios de nombres separados, y he encontrado que es un enfoque muy limpio.¿Existe alguna forma clara de agregar funciones a un espacio de nombres creado dinámicamente?

De acuerdo con esto, necesito ser capaz de crear dinámicamente nuevos espacios de nombres que correspondan a vistas y modelos, y luego internar las funciones apropiadas en ellos. Mi idea era tener las macros especificadas en un espacio de nombres separado que, cuando se llamara en el nuevo espacio de nombres, proporcionaría las rutas/parciales/lo que sea apropiado.

Por ejemplo (valga mi primer defmacro):

(ns project.views.proto 
    (:use noir.core 
     hiccup.core 
     hiccup.element 
     hiccup.form)) 

(defmacro def-all-page 
    [path] 
    `(defpage ~path [] 
    (html 
     [:h1 "Ya'll here"]))) 

se llama desde ...

(ns project.proto 
    (:use [clojure.contrib.with-ns :only [with-ns]]) 

(create-ns 'foo) 
(intern 'foo 'path "path") ; In reality, the path is dynamic which is why I intern it 
(with-ns 'foo 
    (clojure.core/refer-clojure) 
    (use 'noir.core 
     'hiccup.core 
     'hiccup.element 
     '[project.views.proto :only [def-all-page]]) 

    (def-all-page path) 

Sin embargo, me llama esto desde dentro de mi nuevo espacio de nombres da una NullPointerException. Agradecería mucho cualquier ayuda, y si hay un mejor enfoque. ¿Me gusta, simplemente usa referir para un espacio de nombres que contiene todas las definiciones necesarias?

Primera publicación, y no creo que sea una repetición de this. ¡Gracias!

+0

¿Consideraría editar su publicación e indicar su espacio de nombre y algún ejemplo de código de Clojure que invoca la macro? Me gustaría ver en qué contexto se usa. tnx – octopusgrabbus

+1

Espero que sea un poco más útil. – jtmoulia

+0

El error que recibo es Imposible resolver el símbolo: with-ns en este contexto, compilando, pero no sé si eso significa que puede usar with-ns fuera de una función o macro. – octopusgrabbus

Respuesta

1

En primer lugar, esta pregunta se ha quedado un poco desactualizada. Tanto Noir como Clojure han evolucionado durante el último año. En aras de la claridad, sacaré a Noir de la ecuación y trataré de responder a su pregunta sobre la creación dinámica de funciones usando macros.

lo sigue en el REPL:

$ lein repl 
user=> (in-ns 'foo) 
#<Namespace foo> 
foo=> (clojure.core/refer-clojure) 
nil 
foo=> (defmacro say-hello-to 
#_=>   [name] 
#_=>   `(defn ~(symbol (str "hello-" name)) 
#_=>     [] 
#_=>     ~(str "hello: " name))) 
#'foo/say-hello-to 

Aquí creamos un 'foo' que contiene una macro para definir funciones 'hola-yourname' espacio de nombres. Vamos a crear otro espacio de nombres:

foo=> (in-ns 'bar) 
#<Namespace bar> 
bar=> (clojure.core/refer-clojure) 
nil 
bar=> (refer 'foo :only '[say-hello-to]) 
nil 
bar=> (say-hello-to "tom") 
#'bar/hello-tom 
bar=> (say-hello-to "jerry") 
#'bar/hello-jerry 

Vamos a ver si éstos funcionan en realidad:

bar=> (hello-tom) 
"hello: tom" 
bar=> (hello-jerry) 
"hello: jerry" 

Creo que esto es bastante cerca de su original ejemplo.

Espero que esto ayude!

Cuestiones relacionadas