2012-04-22 16 views
11

Sto creando una webapp noir e ho bisogno di creare dinamicamente nuove viste e modelli. Ho seguito gli esempi noir, in cui la vista e il controller di una risorsa hanno spazi dei nomi separati e ho trovato che si tratta di un approccio molto pulito.Esiste un modo pulito per aggiungere funzioni a uno spazio dei nomi creato in modo dinamico?

In linea con questo, ho bisogno di essere in grado di creare dinamicamente nuovi spazi dei nomi corrispondenti a viste e modelli, quindi internare le funzioni appropriate al loro interno. La mia idea era di avere delle macro specificate in uno spazio dei nomi separato che, quando chiamato nel nuovo spazio dei nomi, avrebbe fornito i percorsi appropriati/parziali/qualunque.

Per esempio (perdonate il mio primo 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"]))) 

viene chiamato da ...

(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) 

Tuttavia, mi chiama questo da dentro il mio nuovo spazio dei nomi dà una NullPointerException. Apprezzerei molto ogni aiuto e se ci fosse o meno un approccio migliore. Come, basta usare refer per uno spazio dei nomi che contiene tutte le definizioni necessarie?

Primo post, e non penso sia una ripetizione di this. Grazie!

+0

Considereresti di modificare il tuo post e di indicare il tuo spazio dei nomi e qualche esempio di codice Clojure che richiama la macro? Mi piacerebbe vedere in quale contesto è usato. tnx – octopusgrabbus

+1

Spero sia un po 'più utile. – jtmoulia

+0

L'errore che sto ottenendo è Impossibile risolvere il simbolo: con -ns in questo contesto, compilando, ma non so se questo significa che puoi usare with-ns al di fuori di una funzione o di una macro. – octopusgrabbus

risposta

1

Prima di tutto, questa domanda è diventata un po 'obsoleta. Sia Noir che Clojure si sono evoluti nell'ultimo anno. Per motivi di chiarezza, prenderò Noir fuori dall'equazione e cercherò di rispondere alla tua domanda sulla creazione dinamica di funzioni usando le macro.

seguire insieme al 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 

Qui creiamo uno spazio dei nomi 'foo' che contiene una macro per definire le funzioni di 'Ciao-nomeutente'. Creiamo un altro spazio dei nomi:

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 

Vediamo se questi realmente funzionano:

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

Penso che questo sia abbastanza vicino al vostro esempio originale.

Spero che questo aiuti!

Problemi correlati