2012-04-22 15 views
11

Tworzę aplikację internetową noir i muszę dynamicznie tworzyć nowe widoki i modele. Śledziłem przykłady noir, w których widok i kontroler dla zasobu mają oddzielne przestrzenie nazw i uważam, że jest to bardzo czyste podejście.Czy istnieje czysty sposób dodawania funkcji do dynamicznie tworzonego obszaru nazw?

Zgodnie z tym, muszę mieć możliwość dynamicznego tworzenia nowych przestrzeni nazw odpowiadających widokom i modelom, a następnie internować w nich odpowiednie funkcje. Mój pomysł polegał na tym, aby makra były określone w oddzielnej przestrzeni nazw, która po wywołaniu w nowej przestrzeni nazw zapewniłaby odpowiednie trasy/części/cokolwiek.

Na przykład (wybacz mój pierwszy 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"]))) 

jest wywoływana z ...

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

Jednak wywołanie to od wewnątrz mojego nowego nazw daje mi NullPointerException. Byłbym bardzo wdzięczny za każdą pomoc i czy istnieje lepsze podejście. Jak, po prostu za pomocą odnoszą się do przestrzeni nazw, która zawiera wszystkie niezbędne definicje?

Pierwszy wpis, i nie sądzę, że jest to powtórka z this. Dzięki!

+0

Czy rozważasz edytowanie swojego postu i oznaczenie swojej przestrzeni nazw i przykładowego kodu Clojure, który wywołuje makro? Chciałbym zobaczyć, w jakim kontekście jest on używany. tnx – octopusgrabbus

+1

Mam nadzieję, że to trochę bardziej pomocne. – jtmoulia

+0

Błąd, który dostaję, jest niemożliwy do rozstrzygnięcia symbol: with-ns w tym kontekście, kompilacja, ale nie wiem, czy to oznacza, że ​​możesz użyć funkcji -ns poza funkcją lub makrem. – octopusgrabbus

Odpowiedz

1

Po pierwsze, to pytanie stało się nieco przestarzałe. Zarówno Noir, jak i Clojure ewoluowały przez ostatni rok. Dla jasności wybiorę Noira z równania i spróbuję odpowiedzieć na twoje pytanie dotyczące dynamicznego tworzenia funkcji za pomocą makr.

Idź wzdłuż na 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 

Tutaj tworzymy nazw 'foo', który zawiera makro definiowania funkcji 'hello-YourName. Stwórzmy inną przestrzeń nazw:

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 

Zobaczymy, czy to rzeczywiście działa:

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

myślę, że to jest dość blisko do oryginalnego przykładu.

Mam nadzieję, że to pomoże!

Powiązane problemy