2012-04-22 1 views
11

Я создаю noir webapp, и мне нужно динамически создавать новые виды и модели. Я слежу за примерами noir, в которых представление и контроллер для ресурса имеют отдельные пространства имен, и я нашел, что это очень чистый подход.Есть ли чистый способ добавить функции в динамически созданное пространство имен?

В связи с этим мне нужно иметь возможность динамически создавать новые пространства имен, соответствующие представлениям и моделям, а затем ставить в них соответствующие функции. Моя идея заключалась в том, чтобы макросы указывались в отдельном пространстве имен, которое при вызове в новом пространстве имен предоставляло соответствующие маршруты/partials/whatever.

Например (простите мой первый 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"]))) 

вызывается из ...

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

Однако, называя это внутри моего нового пространства имен дает мне NullPointerException. Я бы очень признателен за любую помощь, и есть ли лучший подход. Например, просто используя ссылку для пространства имен, которое содержит все необходимые определения?

Первое сообщение, и я не думаю, что это повторение this. Благодаря!

+0

Обсудите ли вы редактирование своего сообщения и укажите пространство имен и образец кода Clojure, который вызывает макрос? Я хотел бы видеть, в каком контексте он используется. tnx – octopusgrabbus

+1

Надеюсь, это немного полезно. – jtmoulia

+0

Ошибка, которую я получаю, не может разрешить символ: с-ns в этом контексте, компиляция, но я не знаю, означает ли это, что вы можете использовать с-ns вне функции или макроса. – octopusgrabbus

ответ

1

Прежде всего, этот вопрос немного устарел. За последний год оба Нойра и Клоджуре развились. Для ясности я возьму Noir из уравнения и постараюсь ответить на ваш вопрос о динамическом создании функций с помощью макросов.

Проследите на РЕПЛ:

$ 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 

Здесь мы создаем пространство имен «Foo», который содержит макрос для определения «привет-ВашеИмя» функции. Давайте создадим еще одно пространство имен:

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 

Давайте посмотрим, если они действительно работают:

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

Я думаю, что это довольно близко к исходному примеру.

Надеюсь, это поможет!